Node.js: how to run asynchronous code sequentially

I have this piece of code

User.find({}, function(err, users) {
    for (var i = 0; i < users.length; i++) {
        pseudocode
        Friend.find({
            'user': curUser._id
        }, function(err, friends) * * ANOTHER CALLBACK * * {
            for (var i = 0; i < friends.length; i++) {
                pseudocode
            }
            console.log("HERE I'm CHECKING " + curUser);
            if (curUser.websiteaccount != "None") {
                request.post({
                    url: 'blah',
                    formData: blah
                }, function(err, httpResponse, body) { * * ANOTHER CALLBACK * *
                        pseudocode
                    sendMail(friendResults, curUser);
                });
            } else {
                pseudocode
                sendMail(friendResults, curUser);
            }
        });
        console.log("finished friend");
        console.log(friendResults);
        sleep.sleep(15);
        console.log("finished waiting");
        console.log(friendResults);
    }
});

A couple of asynchronous things happen here. For each user, I want to find their respective friends and combine them with a variable. Then I want to check if this user has a website account, and if so, make a mail request and get some information there. The only thing is that everything happens out of order, since the code does not wait for the callbacks to complete. I use sleep, but this does not solve the problem either since it is still confused.

I looked at async, but these functions are intertwined and not shared, so I was not sure how it would work with async.

Any suggestions for this code to run sequentially?

Thank!

+4
6

q https://www.npmjs.com/package/promise -

var Promises = require('promise');
var promise = new Promises(function (resolve, reject) {
    // do some async stuff
    if (success) {
        resolve(data);
    } else {
        reject(reason);
    }
});
promise.then(function (data) {
    // function called when first promise returned
    return new Promises(function (resolve, reject) {
        // second async stuff
        if (success) {
            resolve(data);
        } else {
            reject(reason);
        }
    });
}, function (reason) {
    // error handler
}).then(function (data) {
    // second success handler
}, function (reason) {
    // second error handler
}).then(function (data) {
    // third success handler
}, function (reason) {
    // third error handler
});

, . promises async, then.

+5

, . , , :

- - (, pseucode). , .

async , , , /.

User.find({}, function(err, users) {
  for (var i = 0; i < users.length; i++) {
    Friend.find({'user':curUser._id}, function(err, friends) {
      for (var i = 0; i < friends.length; i++) {
        // pseudocode
      }
      console.log("HERE I'm CHECKING " + curUser);
      if (curUser.websiteaccount != "None") {
        request.post({ url: 'blah', formData: 'blah' }, function(err, httpResponse, body) {
          // pseudocode
          sendMail(friendResults, curUser);
        });
      } else {
        // pseudocode
        sendMail(friendResults, curUser);
      }
    });

    console.log("finished friend");
    console.log(friendResults);
    sleep.sleep(15);
    console.log("finished waiting");
    console.log(friendResults);
  }
});
+2

var users = User.find({});

users.forEach(function (user) {
  var friends = Friend.find({
    user: user._id
  });
  friends.forEach(function (friend) {
      if (user.websiteaccount !== 'None') {
         post(friend, user);
      }
      sendMail(friend, user);
  });
});

,

async.waterfall([
  async.apply(Users.find, {}),
  function (users, cb) {
    async.each(users, function (user, cb) {
      async.waterfall([
        async.apply(Friends.find, { user, user.id}),
        function (friends, cb) {
          if (user.websiteAccount !== 'None') {
            post(friend, user, function (err, data) {
              if (err) {
                cb(err);
              } else {
                sendMail(friend, user, cb);
              }
            });
          } else {
            sendMail(friend, user, cb);
          }
        }
      ], cb);
    });
  }
], function (err) {
  if (err) {
    // all the errors in one spot
    throw err;
  }
  console.log('all done');
});

, , SQL .

+2

JavaScript Async: Async JavaScript.

+1

: , , , . , . , !

, , psuedocode IMHO, , :

  • , . :
    • , -
  • Do something after the process is complete.

You can do this in many ways. Vanilla callbacks or async work fine; I will defend promises , because this is the future, and library support is not bad. I will use rsvp because it is light, but any Promise / A + compatible library will do the trick.

// helpers to simulate async calls
var User = {}, Friend = {}, request = {};
var asyncTask = User.find = Friend.find = request.post = function (cb) {
  setTimeout(function () {
    var result = [1, 2, 3];
    cb(null, result);
  }, 10);
};

User.find(function (err, usersResults) {
  // we reduce over the results, creating a "chain" of promises
  // that we can .then off of
  var userTask = usersResults.reduce(function (outerChain, outerResult) {
    return outerChain.then(function (outerValue) {
      // since we do not care about the return value or order
      // of the asynchronous calls here, we just nest them
      // and resolve our promise when they are done
      return new RSVP.Promise(function (resolveFriend, reject){
        Friend.find(function (err, friendResults) {
          friendResults.forEach(function (result) {
            request.post(function(err, finalResult) {
              resolveFriend(outerValue + '\n finished user' +  outerResult);
            }, true);
          });
        });
      });
    });
  }, RSVP.Promise.resolve(''));

  // handle success
  userTask.then(function (res) {
    document.body.textContent = res;
  });

  // handle errors
  userTask.catch(function (err) {
    console.log(error);
  });
});

jsbin

+1
source

Source: https://habr.com/ru/post/1569563/


All Articles