Mean.io framework with socket.io - angularjs

How to use socket.io in Mean.io stack?
First of all, Mean.io changes their folder structure very regularly.. So my question is where is the best place to configure socket.io ? or is it better to use express.io ?
Second I am still not quite sure where to look for to find code that tells mean.io to listen for port, I have found a port is defined in config folder in all.js file, but real problem is as soon as I define server.listen(port) app doesn't load. and if I don't app loads but socket.io doesn't work.
Also I have another question about /socket.io/socket-io.js file? I have copied that in index folder, but my app can't find it or says 404 error. I know it's not an actual file sitting on any such location as far as I have understood, also people suggested to put that line as 127.0.0.1/socket.io/socket-io.js but none made the js file available for the app to be able to run socket.io.
What is the proper way of defining socket.io in mean.io framework?

I also faced the same issue and took me about a week to finally get it right. I'll try to explain what I did:
app.js
In this file, I just invoke the code that creates and sets up a socket.io object for me, which is then passed to the routes module.
'use strict';
/*
* Defining the Package
*/
var Module = require('meanio').Module;
var MeanSocket = new Module('chat');
/*
* All MEAN packages require registration
* Dependency injection is used to define required modules
*/
MeanSocket.register(function(app, http) {
var io = require('./server/config/socketio')(http);
//We enable routing. By default the Package Object is passed to the routes
MeanSocket.routes(io);
return MeanSocket;
});
server/config/socketio.js
This file simply configures the socket.io object. Please note that I had to upgrade meanio module to version 0.5.26 for this work, as http object (express server) is not available in older meanio versions. Moreover, in case you want to use ssl, you can inject https instead of http.
'use strict';
var config = require('meanio').loadConfig(),
cookie = require('cookie'),
cookieParser = require('cookie-parser'),
socketio = require('socket.io');
module.exports = function(http) {
var io = socketio.listen(http);
io.use(function(socket, next) {
var data = socket.request;
if (!data.headers.cookie) {
return next(new Error('No cookie transmitted.'));
}
var parsedCookie = cookie.parse(data.headers.cookie);
var sessionID = parsedCookie[config.sessionName];
var parsedSessionID = cookieParser.signedCookie(parsedCookie[config.sessionName], config.sessionSecret);
if (sessionID === parsedSessionID) {
return next(new Error('Cookie is invalid.'));
}
next();
});
return io;
};
routes/chat.js
Finally, use the routes file to define the socket events, etc.
'use strict';
// The Package is passed automatically as first parameter
module.exports = function(MeanSocket, io) {
io.on('connection', function(socket) {
console.log('Client Connected');
socket.on('authenticate', function(data, callback) {
});
});
};
Hope this helps!

The simplest way would be to install the socket package...
mean install socket

Related

How to get config values from server in Angular?

My application needs some config values on application startup. Suggestions from the community is to store them as constant as separate module, preferably in separate .js file. This might work for me.
However my configuration values are also stored on the server, and dont want to duplicate those on client side, so i was thinking of making server call to get those.
Im newbie to angular, is it valid design practice to make server call in module's config method? If yes then should i just use $http service to get the values from the server?
var main = angular.module('myapp', ['AdalAngular']);
main.config(['$stateProvider',$httpProvider, adalAuthenticationServiceProvider', function ($stateProvider,$httpProvider,adalProvider) {
// $stateProvider configuration goes here
// ?????CAN I make server call here to get configuration values for adalProvider.init method below???
adalProvider.init(
{
instance: 'someurl',
tenant: 'tenantid',
clientId: 'clientid',
extraQueryParameter: 'someparameter',
cacheLocation: 'localStorage',
},
$httpProvider
);
}]);
main.run(["$rootScope", "$state", .....
function ($rootScope, $state,.....) {
// application start logic
}]);
main.factory("API", ["$http", "$rootScope", function ($http, $rootScope) {
// API service that makes server call to get data
}]);
EDIT1
So based on suggestions below I'm going with declaring constant approach. Basically I will have separate config.js file and during deployment process I will overwrite the config.js file with respective environment based config.js file.
Question
If have to 10 constants then i have to pass them separately to module.config(). Is it possible to declare constant value as JSON object and somehow read it in config function so I don't have pass 10 different parameters?
angular.module('myconfig', [])
.constant('CONFIGOBJECT','{Const1:somevalue,Const2:somevalue,Const3:somevalue,Const4:somevalue}');
and then how do I read the values in config method?
var main = angular.module('myapp',['myconfig']);
main.config(['CONFIGOBJECT',function(CONFIGOBJECT){
?? How do I read CONFIGOBJECT value that is a string not json object?
})
I'll describe the solution used in project that i was working on some time ago.
It's true that you cannot use services in config phase, and it's also true, that you can use providers and constants while config phase.
So we used the next solution:
firstly, we created simple object with config, like
var config = {
someConfig1: true,
someConfig2: false,
someConfigEvents: {
event1: 'eventConfig1',
event2: 'eventConfig2'
}
etc...
}
Then we also declared angular value with jQuery lib:
app.value('jQuery', jQuery);
And now we cannot use services like $http, but we can use jQuery, so we just making ajax call to config server and extending our config:
jQuery.ajax("path/to/config", { async: false, cache: false })
.done(function (data) {
var response = angular.fromJson(data)
if (response) {
angular.extend(config, response.returnData.data);
} else {
alert('error');
}
})
.fail(function () {
alertError();
})
.always(function () {
appInit();
});
You cannot inject a service into the config section.
You can inject a service into the run section.
So, you cannot use - for example $http service to retrieve data from server inside config() , but you can do in inside run(), which initializes the provider's service.
See also more complete answer here.
Hope this helps.
UPDATE:
Why string? Why don't you simply use
.constant('CONFIGOBJECT', {Const1:somevalue,Const2:somevalue,Const3:somevalue,Const4:somevalue}
for
.constant('CONFIGOBJECT', '{Const1:somevalue,Const2:somevalue,Const3:somevalue,Const4:somevalue}'
?
Only providers are available during the config phase, not services. So you can't use $http during this phase.
But you can use it during the execution phase (in a function passed to run()).
An alternative is to have some JavaScript file dynamically generated by the server, and defining the constants you want.
Another alternative is to generate such a JS file during the build, based on some file that would be read by the server-side code.

Calling nodeJS from angularJS function

I have one function which block one room from room list via ajax call here is function
$scope.blockThisRoom = function(room, index){
// ajax call an validation
}
I have setup nodeJs script
var http = require('http');
var url = require('url');
var fs = require('fs');
var server;
var io = require('socket.io').listen(server);
server = http.createServer(function(req, res){
var queryObject = url.parse(req.url,true).query;
console.log(queryObject)
}),
and it gives query object while I am doing testing.
My Problem
I want to call nodeJS script when $scope.blockThisRoom function is call but I am confuse how to call node function.... , should I include nodeJS script as we add other javascript files in my view
or
I call nodeJS file a via ajax calling like below is code
$scope.testController = function() {
var url = "http://localhost:8076?id=1&type=block";
$http.get(url).success( function(response) {
$scope.students = response;
});
}
Angular and node are differents : NodeJs is executed in server, and angular in client. So If you try to include node script and run it on client browser, It will just not work... The two are javascripts, but not linked by any ways: you can use angular on PHP projects, and you can use Node.js without angular. It is just the fact that the two technologies are powerful when used together...
Effectively, I suggest to use Ajax call, with parameters you want (use $http.post instead of $http.get if you want to send a long query, or if you want to send arrays or objects... because with node and Angular post, you can send/parse JSON strings!!)

socket connection always failing

I'm writing an application that connects to a sails server.
This application is written with cordova, angularJS and Ionic.
When I launch my application in my browser (with ionic serve) the socket fails to connect to the server. Here is the message I get:
GET http://localhost:8100/socket.io/?__sails_io_sdk_version=0.11.0&__sails_io_s…sails_io_sdk_language=javascript&EIO=3&transport=polling&t=1443472067762-4 404 (Not Found)
The server is running locally on port 1337. I tried to change the above URL to:
http://localhost:1337/socket.io/?__sails_io_sdk_version=0.11.0&__sails_io_s…sails_io_sdk_language=javascript&EIO=3&transport=polling&t=1443472067762-4
and it's working.
In my code I set the URL after sails.io.js has been included:
io.sails.url = 'http://localhost:1337';
io.sails.useCORSRouteToGetCookie = false;
Why is it asking to localhost:8100 and not localhost:1337?
When I launch this application in my mobile device (setting the url to http://192.168.1.10:1337) it's working correctly.
Version of sails.io.js is 0.11.6, and version of sails is 0.11.0
localhost:8100 wont work in your mobile development environment. I faced same issue and changing localhost to your workstation's ip solved the problem
I finally found the solution (but I'm sorry I can't recall where I found it :()
The problem was that the io.sails.url = 'http://localhost:1337'; was executed after the first JS cycle, and thus the sails socket was already loaded. (that's (from what I understood) because in some browsers if the code is in another script tag it is executed in another cycle)
To make it work I had to add this code before I include the sails socket script:
var apiHost = 'localhost';
(function (){
var io;
Object.defineProperty(window, 'io', {
get: function (){
return io;
},
set: function (value){
var sails;
io = value;
Object.defineProperty(io, 'sails', {
get: function (){
return sails;
},
set: function (value){
sails = value;
sails.url = 'http://'+apiHost+':1337';
sails.useCORSRouteToGetCookie = false;
}
});
}
});
})();

Modify or access angular interceptors after config phase

Is it possible to access / modify $http interceptors after the config phase? I'm debugging an app that only breaks in production due to being deployed on a different server, so unfortunately I can't change the interceptor code locally and figure out what's going on.
If it's not possible to access / modify the interceptors, perhaps it'd be possible to replace $http. Here's an example of replacing a hypothetical service:
var inj = angular.element('body').injector(),
oldGet = inj.get,
mockService = { secret: 'shhh' };
inj.get = function(str) {
if (str === 'some-service') {
return mockService;
} else {
return oldGet.apply(inj, arguments);
}
};
However, I'm not sure how I'd go about creating a new $http service (into which I could pass in the modified interceptors). I can't grab the $httpProvider, either.
Perhaps bootstrapping a new ng-app on a separate part of the page would work? Then I could grab the $http service and replace it, like above.
Other ideas:
With reference to: Right way to disable/remove http interceptors in Angular? , it does not seem like I can access the interceptors array if I don't hold on to it in the config phase.
Perhaps I can use grease monkey to inject something that runs in the config phase.
Thank you!

SignalR: How to add client call after the hub is started?

First off, I just started trying to add SignalR 2 to my existing Angular SPA project.
I have a main controller which starts the hub right away that is feeding some messages to the client. Inside, I have several sub pages and each could subscribe to a different hub for services. The problems is that the client doesn't receive message because it is hooked up after the hub is already started in the main controller.
As a test, if I comment out the hub start in the main controller, the one in the sub controller works fine.
From what I read, it is by design that you have to hook up all client calls before starting the hub. I don't understand...if it is a service, I should be able to subscribe or unsubscribe anytime after the hub is started. Why not? How to workaround?
Because no response in the 12 hours (which is quite unusual in so), I had to dig around myself. I think, I was misled by the answers from SO on related questions that you have to subscribe all client call before starting the connection, as mentioned e.g. here. I found in Hubs API Guide, one section says
Define method on client (without the generated proxy, or when adding
after calling the start method)
So, it is possible to add client method after connection is started. The trick is to use so-called "without the generated proxy". That limitation is for "with generated proxy".
The following is my working example taken from SignalR get started tutorial.
This is the main controller using "with generated proxy":
$.connection.statusHub.client.updateStatus = function (status) {
$scope.status = status;
$scope.$apply();
}
$.connection.hub.start();
This is in a subcontroller using "without generated proxy":
var connection = $.hubConnection();
var proxy = connection.createHubProxy('stockTickerHub');
proxy.on('updateStockPrice', function (stock) {
var st = $scope.stocks.firstOfKey(stock.symbol, 'symbol');
st.lastPrice = stock.lastPrice;
$scope.$apply();
});
var hub = $.connection.stockTickerHub;
connection.start().done(function () {
hub.server.getAllStocks().done(function (stocks) {
$scope.stocks = stocks;
});
});
Note that it doesn't work if I use "with generated proxy" in the subcontroller like this:
var hub = $.connection.stockTickerHub;
hub.client.updateStockPrice = function (stock) {
var st = $scope.stocks.firstOfKey(stock.symbol, 'symbol');
st.lastPrice = stock.lastPrice;
$scope.$apply();
};
$.connection.hub.start().done(function () {
hub.server.getAllStocks().done(function (stocks) {
$scope.stocks = stocks;
});
});
To prove the limitation of "with generated proxy" mode, this code works if I comment out the one in the main controller.
By the way, I was so confused by the term with or without generated proxy in the Guide, and in both cases, it is still called xxxProxy. Can't they find a better name? Or somebody has an explanation?

Resources