I'm trying to integrate sending real-time information through sockets (using socket.io ), and sending push notifications using the OneSignal platform .
It happens that if I put everything in the same module, I don't know why the method to send the notification is not executed after the information is sent, or before sending the information.
If I execute the command npm start
, no error appears, but the notification arrives as soon as the local or remote server is running, and in this way I do not want it to happen.
user.js
var express = require('express');
var router = express.Router();
var misocket = require('../routes/misocket');
var notificacion = require('../routes/notificacion');
/*
Si pongo esto asi, apenas envia el servidor, arranca de una vez y envia la notificacion
notificacion();
*/
/* GET users listing. sendnote*/
router.post('/sendasig', function (req, res, next) {
console.log(misocket); //registrednote
misocket.emit("registrar", req.body);
//La idea es que se ejecute aqui, pero no logro hacer que esto suceda
notificacion();
console.log(req.body);
res.status(200).json({
message: "send message"
});
});
module.exports = router;
notification.js
module.exports = function () {
var OnesignalNotificationApi = require('onesignal-notification');
var api = new OnesignalNotificationApi('N2FkY2ZkZWQtMGQ2MS00ZTUwLTlkM2QtODA2NmE0YjBiMzQ3',
'c4b92cce-4d59-4550-a4be-20939370e39c');
var message = {
it: 'Some message',
en: 'Some message',
es: 'Nueva Calificacion'
};
api.sendToAll(message, null, function (err, res) {
console.log(err);
console.log(res);
});
};
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var misocket = require('./routes/misocket');
var index = require('./routes/index');
var users = require('./routes/users');
var io = require("socket.io");
var app = express();
app.io = io();
var Twitter = require('twitter');
var client = new Twitter({
consumer_key: 'XXX',
consumer_secret: 'XXX',
access_token_key: 'XXX',
access_token_secret: 'XXX'
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
//app.use('/api', users);
app.post("/sendnote",function(req,res,next){
app.io.emit("registrednote",req.body);
res.status(200).json({
message : "send message"
});
});
//copias y modificas la ruta del post
app.post('/sendasig', function(req, res, next) {
app.io.emit("registrar",req.body);
res.status(200).json({
message : "send message"
});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
misocket.connection(app.io);
module.exports = app;
You have several problems. First, it's not the right way to integrate express and socket.io. You're not actually creating any socket servers with that code. The correct is:
The above code creates a server using the
http
native nodejs module and also the express server. Finally, create a socket server using the newly created server. At this point, you already have your http server and socket up and running.Another point is that you export as much
app
assocketServer
to be used by other modules.It is very important that you understand the flow of your application, so that you know at what point the dependencies of other modules will be ready in another. For example, take a look at the following:
users.js
app.js
You have a circular dependencies problem. This means that, when you import
users
at the top of your fileapp.js
, itusers.js
will try to importio
fromapp.js
but will getundefined
because it hasn't been created or exported yet . What you have to do here is arrange your code to fit the flow:The third problem I see is that you don't understand the concept of asynchrony. Your module
notificacion
executes asynchronous code when sending push notifications viaOneSignal
, it is always recommended that these be sent before sending an http response if it is executed within a request. Therefore, you could cast that module to return a promise:This will allow you to carry a much more comfortable asynchronous flow in
users.js
:--
As a final piece of advice, I highly recommend you start using ES6+. Node.js has very advanced out-of-the-box support, such as asynchronous functions (
async/await
). Using ES6+ will mean better, more concise, maintainable, and efficient code.In socket.io API you can see the arguments that you can pass to the emit function, they are the name of the event, arguments and callback that is executed when the response from the client is received.
It is missing to include the client response with the callback: