0

On my Node JS backend I run this method.

var locations = [];

exports.constructionsiteParser = function constructionsiteParser(response){
    var timestamp = new Date().toDateInputValue();
    const $ = cheerio.load(response);
    $('situation').each( function(){
    var situation = [];
        $(this).find('situationRecord').each( function(i){
          var startLocationCode = $(this).find('alertCMethod2SecondaryPointLocation').find('specificLocation').text();
      var endLocationCode = $(this).find('alertCMethod2PrimaryPointLocation').find('specificLocation').text();
      var overallStartTime = $(this).find('overallStartTime').text();
      var overallEndTime = $(this).find('overallEndTime').text();
      if((startLocationCode != '') && new Date(timestamp) >= new Date(overallStartTime) && new Date(timestamp) <= new Date(overallEndTime) ){
        Promise.all([
          locationCodeToGeodataRequst.geodataByLocationcode(startLocationCode), 
          locationCodeToGeodataRequst.geodataByLocationcode(endLocationCode) 
        ]).then( values =>{
          return createSituationRecord($, this, startLocationCode, endLocationCode, values[0], values[1]);
        }).then( function(obj){
          console.log("before push", situation);
          situation.push(obj);
          console.log("after push", situation);
          return situation;
        }, handleError);
      }
    })
    console.log("from outter", situation.length);
    if(situation.length > 0){ //if situation is not empty
      locations.push(situation);
    }
   })
        console.log(locations);
  }

The console.log("from outter", situation.length); at the bottom prints always 0 also the console.log(locations) is empty

This is a part of the log:

...
from outter 0
from outter 0
from outter 0
from outter 0
from outter 0
[]
before push []
after push [....

I think this happens because the node server runs the bottom part before the inner each loop finishes. So I want to make it more snychronized. What I want to do is something like:

outer each{

  //run this first
  inner each{
  .....
  }

  //if inner each is done run this
  if(...){}

}

But I don't know how to put this in the correct syntax. I have tried it with nested Promises but it doesn't work.

3 Answers 3

2

you can return this promise. deal it at caller

Sign up to request clarification or add additional context in comments.

Comments

1

You can make use of async.eachOf(). I took a different approach in making your code synchronous. Hope it helps you.

'use strict';


let locations = [];

exports.constructionsiteParser = function constructionsiteParser(response) {
  const $ = cheerio.load(response);

  $('situation').each(function () {
    let situation = [];

    async.eachOf($(this).find('situationRecord'), function (value, key, callback) {
      innerLoop(callback);
    }, function (err, situation) {
      if (err) {
        return console.error(err.message);
      }

      console.log("from outter", situation.length);

      // this will run only if the inner loops completes
      if (situation.length > 0) { //if situation is not empty
        locations.push(situation);
      }
    });


  });
  console.log(locations);
};

function innerLoop(callback) {
  let startLocationCode = $(this).find('alertCMethod2SecondaryPointLocation').find('specificLocation').text();
  let endLocationCode = $(this).find('alertCMethod2PrimaryPointLocation').find('specificLocation').text();
  let overallStartTime = $(this).find('overallStartTime').text();
  let overallEndTime = $(this).find('overallEndTime').text();

  if (isInvalid(startLocationCode, overallStartTime, overallEndTime)) {
    return callback('some error msg');
  }

  Promise.all([
    locationCodeToGeodataRequst.geodataByLocationcode(startLocationCode),
    locationCodeToGeodataRequst.geodataByLocationcode(endLocationCode)
  ]).then(values => {
    return createSituationRecord($, this, startLocationCode, endLocationCode, values[0], values[1]);
  }).then((obj) => {
    return callback(null, obj);
  }).catch((err) => {
    console.log('err', err.stack);
    return callback(err);
  });
}

function isInvalid(startLocationCode, startTime, endTime) {
  let timestamp = new Date().toDateInputValue();

  let isEmptyCode = startLocationCode === '';
  let isYetToStart = new Date(timestamp) < new Date(startTime);
  let isOver = new Date(timestamp) > new Date(endTime);

  return isEmptyCode || isYetToStart || isOver;
}

Comments

0

You should take a deeper look into promises because they are the way to go for synchronous operations. Maybe try to merge your code into functions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.