javascript – Run a module after making a POST request

Question:

I am trying to integrate sending information in real time through sockets (using socket.io ), and sending push notifications using 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 the information is sent.

If I run the npm start command, I npm start n't see an error but the notification arrives as soon as the local or remote server is running, and this way I don't 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;

Answer:

You have various problems. First, it is not the correct way to integrate express and socket.io. Actually, you are not creating any socket server with that code. The correct is:

var http = require('http')
var io = require("socket.io");
var app = express();
var server = http.createServer(app)
var socketServer = io(server)

The above code creates a server using native http module and also express server. Finally, create a socket server using the newly created server. At this point, you already have your server and working.


Another point is that you export both app and socketServer to be used by other modules.

exports.io = socketServer;
exports.app = app

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

var misocket = require('../app').io;

app.js

var users = require('./routes/users');

You have a circular dependency problem. This means that when you import users at the top of your app.js file, users.js try to import io from app.js but will get undefined because it has not been created or exported yet . What you have to do here is arrange your code to fit the flow:

exports.io = socketServer;
...
app.use('/', require('./routes'));
app.use('/users', require('./routes/users'));
...
misocket.connection(socketServer); // pone el servidor socket en escucha
server.listen(3000, () => console.log('Server started'));
exports.app = app;

The third problem I see is that you don't understand the concept of asynchrony. Your notificacion module executes an asynchronous code when sending push notifications via OneSignal , it is always recommended that these be sent before sending an http response if it is executed within a request. Hence, you could convert that module to return a promise:

module.exports = function() {

  var OneSignal = require('onesignal-notification');
  var api = new OneSignal('N2FkY2ZkZWQtMGQ2MS00ZTUwLTlkM2QtODA2NmE0YjBiMzQ3', 'c4b92cce-4d59-4550-a4be-20939370e39c');
  var message = {
    it: 'Some message',
    en: 'Algún mensaje',
    es: 'Nuevo mensaje',
  };

  return new Promise(function(resolve, reject){
    api.sendToAll(message, null, function(err, res) {
      if (err) {
        reject(err.message);
      } else {
        resolve(res);
      }
    });
  });
};

This will allow you to carry a much more comfortable asynchronous flow in users.js :

router.post('/sendasig', function (req, res) {
  misocket.emit("registrar", req.body);
  notificacion()
    .then(function(response) {
      res.status(200).json({
        message: "send message"
      });
    })
    .catch(function(err) {
      res.status(200).json({
        message: "send message"
      });
    });
});

As a last tip, 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 code, more concise, maintainable and efficient.

Scroll to Top