AngularJS - Socket.io - ExpressJS : How to set up a realtime counter? - angularjs

My purpose is to create a realtime counter. Actually I'm creating files with my server. And I want for every created file, the counter to be incremented (the client should see the number of files in the browser growing...)
How can I exactly do that using Socket.io, AngularJS and Express.js ?
P.S : I have already written some code, but vainly.
EDIT 1 :
public/core.js
var app = angular.module('app', []);
app.factory('socket', function($rootScope){
var socket = io.connect();
return{
on: function(eventName, callback){
socket.on(eventName, function(){
var args = arguments;
$rootScope.$apply(function(){
callback.apply(socket, args);
});
});
},
emit: function(eventName, data, callback){
socket.emit(eventName, data, function(){
var args = arguments;
$rootScope.$apply(function(){
if(callback){
callback.apply(socket.args);
}
});
})
}
};
});
function mainController($scope, $http, socket) {
$scope.formData = {};
socket.on('number', function (data) {
console.log("Socket on number core.js !");
$scope.number = data.numberOfFiles;
});
$scope.initialize = function() {
$scope.formData.search = "";
console.log("initialize() body !");
};
$scope.search = function() {
socket.emit('next', {
message: "next"
});
console.log("search() body !");
$http.post('/search', $scope.formData)
.success(function() {
$('input').val('');
})
.error(function(data) {
console.log('Error: ' + data);
});
};
}
app.js
/**
* Module dependencies.
*/
var express = require('express');
var request = require('request');
var http = require('http');
var path = require('path');
var url = require('url');
var cheerio = require('cheerio'); // builds the DOM tree
var fs = require('fs');
var app = express();
// all environments
app.configure(function() {
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(express.logger('dev')); // log every request to the console
app.use(express.bodyParser()); // pull information from html in POST
app.use(express.methodOverride()); // simulate DELETE and PUT
app.use(express.json());
app.use(express.urlencoded());
app.use(app.router);
});
// app.listen(8080);
// console.log("App listening on port 8080");
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8080);
var numberFiles = 1;
app.post('/search', function(req, res){
var keyword = req.body.search;
for(var i = 0; i < 100; i++) {
// The results' page URL
// some long logic that creates files and increments numberFiles
numberFiles++;
}
});
io.sockets.on('connection', function (socket) {
socket.on('next', function (data) {
socket.emit('number', {
numberOfFiles: numberFiles
});
});
});
app.get('/', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});

Have you tried:
SERVER
io.sockets.on('connection', function (socket) {
socket.on('next', function (data, respond) {
respond({
numberOfFiles: numberFiles
});
});
});
CLIENT
socket.emit('next', {
message: "next"
}, function(data){ // data.numberOfFiles ... };

Related

Node and Angular socket error in browser console

I am using Node(server) + Angular(client) to implement socket in my application.
Angular bower.json socket components : "angular-socket-io":
"^0.7.0","socket.io-client": "^1.7.2",
Node js socket component in package.json : "socket.io": "^1.7.3",
I am seeing this below web socket error in my chrome browser console :
WebSocket connection to
'wss://ireporter.apple.com/uitracker/socket.io/?EIO=3&transport=websocket&sid=4qBY-qoxEzUQZOvUAACb'
failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
WrappedWebSocket # VM43:161
This error happens probably only in a production environment. Cannot remember seeing this error in when running the application in local.
Also posting ONLY the socket related code from both server and client side :
Node js server-side code
start.js file
var express = require('express');
var configure = require("./config/configure");
var logger = require("./config/components/logger")
var app = express();
var server = require('http').Server(app);
server.listen(process.env.PORT || config.port, function() {
logger.info("Express server listening on port", config.port );
});
//Configure with all the basic middlewares and configs
configure(app,server);
configure.js file
var socket = require('./middleware/socket/socket.js');
module.exports = function (app,server) {
app.use(socket(server));
}
socket.js file
"use strict";
var logger = require("../../components/logger");
module.exports = function(server){
var io = require('socket.io')(server, {path: '/appname/socket.io'});
require('./socketServer.js')(io, logger);
return function (req, res, next) {
req.io = io;
next();
};
};
socketServer.js
//export function for listening to the socket
module.exports = function(io, logger) {
io.on('connection', function(socket) {
socket.on('notification:update', function(data) {
io.emit('notification:update', data);
});
});
};
Angular js Client Side code :
Socket.js
MyApp.factory('Socket', function ($rootScope) {
var socket = io.connect('' , {path: '/appname/socket.io'});
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
notificationController.js
Socket.on('notification:update', function(data) {
});
-- Could anyone suggest how to resolve the console error?
Turns out there was another reverse proxy in front of your server that I had no control of. Please check your server setings. the problem is not about the code.
Error during WebSocket handshake: net::ERR_CONNECTION_RESET
Also try this one to test your server side.
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.2/socket.io.js"></script>
<script>
/*var socket = io('', {
path: '/appname/socket.io'
});*/
var socket = io.connect('' , {path: '/appname/socket.io'});
socket.on('notification:update', function (message) {
console.log('notification:update ', message);
});
setTimeout(function() {
console.log('emit demo');
socket.emit('notification:update', 'DEMO');
}, 1000);
socket.on('connect', function (data) {
console.log('connection');
});
</script>

Nodejs callback response not working as expected

I'm trying to authenticate a user based on values entered in a given form. However, after using res.send(), the function at AngularJS controller is not able to correctly redirect user even if the password and username are correct. Am I handling the callbacks correctly?
Controller
<script>
var app = angular.module('myApp', []);
app.controller("loginController", function($scope,$http) {
$scope.sub = function() {
var config = {
headers : {
'Content-Type': 'application/x-www-form-
urlencoded;charset=utf-8;'
}
}
$http.post('/login', { data:{ username: $scope.username,
password: $scope.password} })
.then(function(response){
if(response.state==0){
console.log('Error!');
} else if(response.state==1){
console.log('action on success');
window.location.href = '/views/success.html';}
}).catch(function(error){
console.log('action on error');
});
Authentication
var db = require('../../config');
exports.login = function(req,res){
var username = req.body.data.username;
var password = req.body.data.password;
db.query('SELECT * FROM users WHERE username = ?',[username], function
(error, results, fields){
var result = "0";
if(error) {
console.log('Code 400, Error ocurred');
}
else{
if(results.length>0){
if(results[0].password == password){
console.log('Code 200, login sucessful');
res.json({ state : 1});
}
}
else{
console.log('Code 400, Password or username invalid');
res.json({ state: 0})
}
}
});
}
server.js
var express = require('express');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var db = require('./config');
var app = express();
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.use(morgan('dev'));
app.use(express.static(__dirname + '/app'));
require('./app/routes')(app);
app.listen(3000,function(err){
if(err){
console.log(err);
}
else{
console.log("Listening on port 3000");
}
});
Route.js
var auth = require('../app/middleware/authenticateUser');
module.exports = function (app) {
app.get('/',function(req,res){
res.sendFile(__dirname + '/views/index.html');
});
app.post('/login', function(req, res){
auth.login(req,res);
});
}
Thanks in advance!
You need to inject $window in your controller and then in your successful response
$window.location.href = '/views/success.html';
Although using the $window service is considered AngularJS best practice, I don't think this is where the problem is.
Have you tried console.log() the response object of the $http call?
Maybe the problem is because you put if(response.state) instead of if(response.data.state).

Using Nodejs, Express and AngularJS to display IP in the browser

I'm learning Nodejs and ExpressJS. I'm trying to use ExpressJS and 2 Node modules (request-ip and geoip2) to get the client IP address for geolocation and then outputting the geolocation in the browser using AngularJS (1.x).
So far for my Nodejs and Expressjs code I have
var express = require('express');
// require request-ip and register it as middleware
var requestIp = require('request-ip');
// to convert the ip into geolocation coords
var geoip2 = require('geoip2');
// Init app
var app = express();
var port = process.env.PORT || 8000;
geoip2.init(); // init the db
//app.use(requestIp.mw({ attributeName: 'myCustomAttributeName'}));
var ip = '207.97.227.239';//67.183.57.64, 207.97.227.239
// respond to homepage req
app.get('/', function (req, res, next) {
//var ip = req.myCustomAttributeName;// use this for live
//var ip = '207.97.227.239';/* use this for testing */
console.log('requestIP is ' + ip);
next();
// geolocation
geoip2.lookupSimple(ip, function(error, result) {
if (error) {
console.log("Error: %s", error);
}
else if (result) {
console.log(result);//ipType was causing console.log duplication, IDK why
}
});
});
// set static folder
app.use('/', express.static(__dirname + '/public'));
app.listen(port, function(){
console.log('user location app is running');
});
And for Angular I have
angular.module('UserLocation', []);
angular.module('UserLocation')
.controller('MainController', MainController);
MainController.$inject = ['$http'];
function MainController($http) {
var vm = this;
vm.result = '';
vm.message = 'Hello World';
vm.getLocation = function() {
console.log();
return $http.get('localhost:8000', {
params: {result: result}
})
.then(function(result){
console.log(result);
})
};
};
vm.result in the Angular controller is for the result from the geoip2 Node module that performs the geolocation.
I can get the result in the console no problem but I'm not to sure how to pass it to Angular. I'm using the $http service but I'm not sure where to go from here...?
How do I pass the result from the geoip2 Node module to my Angular controller with $http?
The problem is that you are calling next before you are even done.
app.get('/', function (req, res, next) {
//next(); this line should be commented
// geolocation
geoip2.lookupSimple(ip, function(error, result) {
if (error)
return res.status(400).json({error: 'Something happened'});
return res.send(result);
});
});
Then on angular
$http({
method: 'GET',
url: '/yourURL'
}).then(function (response) {
console.log(response);
});
If you want to use the user IP to get location:
app.get('/', function (req, res, next) {
//next(); this line should be commented
// geolocation
var ip = req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
geoip2.lookupSimple(ip, function(error, result) {
if (error)
return res.status(400).json({error: 'Something happened'});
return res.send(result);
});
});

Is it possible to use socket.io between NodeJS and AngularJS

I have two independent applications (frontEnd and BackEnd). The backEnd is in NodeJS using express framework and the FrontEnd is in AngularJS. Is it possible to use socket.io to send a message from the server (NodeJS) to the client (AngularJS)? How I can do that? I've tried with the following code but it is not working:
server code
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
io.sockets.on('connection', function(socket) {
//This message is not showing
console.log("socket");
socket.volatile.emit('notification', {message: 'push message'});
});
client code
angular.module('pysFormWebApp')
.factory('mySocket', function (socketFactory) {
var mySocket = socketFactory({
prefix: 'foo~',
ioSocket: io.connect('http://localhost:3000/')
});
mySocket.forward('error');
return mySocket;
});
angular.module('formModule')
.controller('typingCtrl', ['$scope', 'mySocket', typingCtrl]);
function typingCtrl ($scope, mySocket) {
mySocket.forward('someEvent', $scope);
$scope.$on('socket:someEvent', function (ev, data) {
$scope.theData = data;
console.log(data);
});
thanks for the help
This is how I set my connection up. I'm not sure if it's the best way, but it definitely works and I haven't had any performance issues to date.
Client Code:
angular.module('whatever').factory('socket', function ($rootScope) {
var socket = io.connect('yourhost');
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
angular.module('whatever').controller("MainCtrl", MainCtrl);
function MainCtrl($scope, socket) {
socket.on('channelname', function(data) {
console.log("message: " + data.message);
});
}
Server Code:
var Express = require('express');
var app = new Express();
var server = Http.createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.emit("channelname", {
message: "messagecontent"
});
});

Using $resource to delete from database

I'm having trouble getting my head around $resource. I'm trying to apply a delete method to remove a MongoDB database entry when user presses a delete button. I am using Angular 1.4 with Express and Mongoose.
Here is my HTML:
<body ng-app="polls" ng-controller="PollsCtrl">
Polls:
<ul>
<li ng-repeat="question in questions">
{{ question.questionName }}
<button ng-click="deletePoll(question._id, $index)">Delete</button>
</li>
</ul>
...
Here's the client-side controller:
"use strict";
var app = angular.module('polls', ['ngResource']);
app.controller('PollsCtrl', function ($scope, $resource) {
var Poll = $resource('/api/polls');
var PollID = $resource('/api/polls/:pollID');
Poll.query(function (results) {
$scope.questions = results;
});
$scope.questions = [];
$scope.questionName = '';
$scope.addPoll = function () {
var poll = new Poll();
poll.questionName = $scope.questionName;
poll.$save(function (result) {
$scope.questions.push(result);
$scope.questionName = '';
});
};
$scope.deletePoll = function (id, index) {
var poll = new PollID();
poll.$remove(function () {
$scope.questions.splice(index, 1);
});
};
});
here's the server file including the remove method:
var express = require('express');
var path = require('path');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var app = express();
mongoose.connect('mongodb://localhost/poll-app');
app.use('/controllers', express.static(__dirname + '/controllers'));
app.use('/bower_components', express.static(__dirname + '/bower_components'));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/polls', function (req, res) {
res.sendFile(path.join(__dirname + '/polls.html'));
});
app.get('/add-poll', function (req, res) {
res.sendFile(path.join(__dirname + '/add-poll.html'));
});
var pollSchema = new mongoose.Schema({questionName: String});
var Poll = mongoose.model('Poll', pollSchema);
var creater = function (req, res) {
var poll = new Poll(req.body);
poll.save(function (err, result) {
if (err) throw err;
res.json(result);
})
};
var list = function (req, res) {
Poll.find({}, function (err, result) {
if (err) throw err;
res.json(result);
});
};
var remove = function (req, res) {
console.log(req.params);
var poll = new Poll(req.body);
poll.remove({_id: req.params}, function (err, result) {
if (err) throw err;
res.json(result);
});
};
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.post('/api/polls', creater);
app.get('/api/polls', list);
app.delete('/api/polls/:pollID', remove);
app.listen(3000, function () {
console.log('HI');
});
I'm pretty sure the error lies in the server's remove() method. When i test this, i actually get:
DELETE http://localhost:3000/api/polls 404 (Not Found)
as though it isn't routing to where i want it to.
poll.$remove({pollID:id}, function () {
$scope.questions.splice(index, 1);
})
in your case, I think it's better to use $http:
$http.delete('/api/polls/pollID/'+req.params).
This way, you don't have to get the object before delete

Resources