H.C
H.C

Reputation: 608

Node script wait for socket event firing before going to the next iteration

Have the following node script that returns

enter image description here

but what pretended was to get: Connecting... success socket closed Connecting... success socket closed Connecting... success socket closed Connecting... success socket closed

by that order. To force the foreach to wait for the events to fire before continuing to the next iteration.

var net = require('net');
var client = new net.Socket();
const fs = require('fs');


var serverPingList = [
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'8089',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
]

serverPingList.forEach(function(server){

  pingPlatforms(server).then(function(result){
     console.log(result);
  }, function(err){
     console.log(err);
  });

})

function pingPlatforms(server){
  return new Promise(function(resolve, reject){
    var logInit = `server ${server.domain} and port ${server.port} Connecting...`
    var log;
    fs.appendFile('ping.log', logInit + '\n', (err) => {
        if(err)
          console.log('Unable to append to server.log.');
    });

    //console.log(server.port);
    //console.log(server.domain);
    console.log('Connecting...')

    //https://stackoverflow.com/questions/8588689/node-js-socket-io-client-connect-failed-connect-error-event
    //https://nodejs.org/api/net.html#net_socket_connect
    var socket = client.connect(server.port, server.domain);
    //var socket = ns_news.socket;

    //the ping failed
    socket.on('error', function(){
        var now = new Date().toString();
        log = `${now}: server ${server.domain} and port ${server.port} Connection Failed`;
        fs.appendFile('ping.log', log + '\n', (err) => {
            if(err)
              console.log('Unable to append to ping.log.');
        });
        resolve('success');
        //client.destroy();
    });
    // the ping is successful
    socket.on('connect', function(){
        console.log('Connected');

        var now = new Date().toString();
        log = `${now}: server ${server.domain} and port ${server.port} Connection Successful`;
        fs.appendFile('ping.log', log + '\n', (err) => {
            if(err)
              console.log('Unable to append to ping.log.');
        });
        resolve('success');
        //client.destroy();
    });

    socket.on('disconnect', function () {
      console.log('Disconnected');
      reject('disconnected');
    });
    socket.on('close', function () {
      console.log('socket closed');
      //client.destroy();
    });
  });
}

Upvotes: 0

Views: 293

Answers (3)

H.C
H.C

Reputation: 608

Got to work it as intended by stop using the forEach using just the pop method of array calling the function again for the next iteration when the promise was resolve or reject (there must be better method of doing this but for now... ). Thanks for the @Nikita Malyschkin and @MadWard for the answers but callback made for me a bit confusing for @MadWard solution and didn't return what was suppose as for @Nikita answer that was a bit my question... how to use promise to force the sync for the foreach cycle (since the node is async).

var net = require('net');
const fs = require('fs');
const async = require("async");

var serverPingList = [
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'8089',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
]

pingAll();


function pingAll(){
  var server = serverPingList.pop();
  var client = new net.Socket();
  pingPlatforms(server,client)
  .then(function(result){
     console.log(result);
     if(serverPingList.length>0)
        pingAll();
  }, function(err){
     console.log(err);
     if(serverPingList.length>0)
        pingAll();
  });
}


function pingPlatforms(server,client){
  return new Promise(function(resolve, reject){
    var logInit = `server ${server.domain} and port ${server.port} Connecting...`
    var log;
    fs.appendFile('ping.log', logInit + '\r\n', (err) => {
        if(err)
          console.log('Unable to append to server.log.');
    });

    //console.log(server.port);
    //console.log(server.domain);


    //https://stackoverflow.com/questions/8588689/node-js-socket-io-client-connect-failed-connect-error-event
    //https://nodejs.org/api/net.html#net_socket_connect
    console.log('Connecting...')
    var socket = client.connect(server.port, server.domain);

    socketEvents(socket,client,server).then(function(result){
       resolve(result);
    }, function(err){
       reject(err)
    });


    /*
    socket.on('disconnect', function () {
      console.log('Disconnected');
      reject('disconnected');
    });
    */
    /*
    socket.on('close', function () {
      console.log('socket closed');
      //socket.disconnect(0);
      //client.destroy();
    });
    */

  });
}

function socketEvents(socket,client,server){
  return new Promise(function(resolve, reject){
    //the ping failed
    socket.on('error', function(){
        var now = new Date().toString();
        log = `${now}: server ${server.domain} and port ${server.port} Connection Failed`;
        fs.appendFile('ping.log', log + '\r\n', (err) => {
            if(err)
              console.log('Unable to append to ping.log.');
        });
        client.destroy();
        reject(log);
    });
    // the ping is successful
    socket.on('connect', function(){
        console.log('Connected');

        var now = new Date().toString();
        log = `${now}: server ${server.domain} and port ${server.port} Connection Successful`;
        fs.appendFile('ping.log', log + '\r\n', (err) => {
            if(err)
              console.log('Unable to append to ping.log.');
        });
        client.destroy();
        resolve('success');
    });
  });
}

Upvotes: 0

Azami
Azami

Reputation: 2161

Instinctively, I would remove promises and use the async.eachSeries function to chain your pings.

Here is an untested snippet adapted from your code:

var net = require('net');
var client = new net.Socket();
const fs = require('fs');
const async = require("async");

var serverPingList = [
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'8089',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
  {
    port:'80',
    domain:'domainexample'
  },
]

async.eachSeries(serverPingList, function(server, callback){

  pingPlatforms(server, function(err){
    if(err){
      console.log("Error on pinging server", server.domain, err);
    }else{
      console.log("Success on pinging server",server.domain);
    }
    return callback();
  });
}, function(){
  console.log("All pings have been sent");
});

function pingPlatforms(server, cb){
  var logInit = `server ${server.domain} and port ${server.port} Connecting...`
  var log;
  fs.appendFile('ping.log', logInit + '\n', (err) => {
      if(err)
        console.log('Unable to append to server.log.');
  });

  //console.log(server.port);
  //console.log(server.domain);
  console.log('Connecting...')

  //https://stackoverflow.com/questions/8588689/node-js-socket-io-client-connect-failed-connect-error-event
  //https://nodejs.org/api/net.html#net_socket_connect
  var socket = client.connect(server.port, server.domain);
  //var socket = ns_news.socket;

  //the ping failed
  socket.on('error', function(){
      var now = new Date().toString();
      log = `${now}: server ${server.domain} and port ${server.port} Connection Failed`;
      fs.appendFile('ping.log', log + '\n', (err) => {
          if(err)
            console.log('Unable to append to ping.log.');
      });
      cb(null);
      //client.destroy();
  });
  // the ping is successful
  socket.on('connect', function(){
      console.log('Connected');

      var now = new Date().toString();
      log = `${now}: server ${server.domain} and port ${server.port} Connection Successful`;
      fs.appendFile('ping.log', log + '\n', (err) => {
          if(err)
            console.log('Unable to append to ping.log.');
      });
      cb(null);
      //client.destroy();
  });

  socket.on('disconnect', function () {
    console.log('Disconnected');
    cb("Error");
  });
  socket.on('close', function () {
    console.log('socket closed');
    //client.destroy();
  });
}

Upvotes: 1

Nikita Malyschkin
Nikita Malyschkin

Reputation: 692

It behaves that way because you use async programming, in that case Promises. Maybe the example below can make it more clear.

x = new Promise((res,rej) => {
  console.log("a");
  res();
  console.log("b");
})
x.then(() => console.log("c"));
console.log("d");
// a
// b
// d
// c

Upvotes: 1

Related Questions