Node.js: How to run asynchronous code sequentially

前端 未结 6 2038
眼角桃花
眼角桃花 2021-01-03 02:37

I have this chunk of code

User.find({}, function(err, users) {
    for (var i = 0; i < users.length; i++) {
        pseudocode
        Friend.find({
              


        
6条回答
  •  迷失自我
    2021-01-03 03:34

    Note: I think the number of queries you are doing within a handler is a code smell. This problem is probably better solved at the query level. That said, let's proceed!

    It's hard to know exactly what you want, because your psuedocode could use a cleanup IMHO, but I'm going to what you want to do is this:

    1. Get all users, and for each user a. get all the user's friends and for each friend:
      • send a post request if the user has a website account
      • send an email
    2. Do something after the process has finished

    You can do this many different ways. Vanilla callbacks or async work great; I'm going to advocate for promises because they are the future, and library support is quite good. I'll use rsvp, because it is light, but any Promise/A+ compliant 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

提交回复
热议问题