【问题标题】:How to run a function after an async function completed in node.js?node.js 中的异步函数完成后如何运行函数?
【发布时间】:2018-01-16 05:14:35
【问题描述】:

我想在我的 forEach 循环之后运行代码。

myPosts.forEach(function(post) {
    getPostAuthor(post.authorID, function(postAuthor) {
        post.author = postAuthor;
    }
});

res.render('index', {
    posts: myPosts
});
res.end();

在上面的代码中,首先 res.render 运行,然后 forEach 填充 post.author

【问题讨论】:

  • forEach 不是异步的。 getPostAuthor 是。
  • 不,但我敢打赌getPostAuthor() 是。
  • 我的意思是 forEach 中的函数
  • 堆栈溢出时这里有数百个重复项。

标签: async javascript node.js asynchronous callback


【解决方案1】:

映射到 Promises 而不是使用 forEach 进行迭代,然后使用 Promise.all:

Promise.all(
 myPosts.map(function(post) {
  return new Promise(function(res){
   getPostAuthor(post.authorID, function(postAuthor) {
      post.author = postAuthor;
      res(postAuthor);
   });
  });
})
).then(function(authors){

  res.render('index', {
     posts: myPosts
   });
  res.end();

});

【讨论】:

  • 您应该在.then() 处理程序中显示res.render(),因为这是OP 试图完成的(在异步操作完成后进行渲染)。顺便说一句,我没有投票 - 不知道为什么有人这样做。
【解决方案2】:

您可以创建一个 promise 数组,然后使用 Promise.all 监听所有完成。

const promises = [];

myPosts.forEach(function(post) {
    const promise = new Promise((resolve) => {
      getPostAuthor(post.authorID, function(postAuthor) {
          post.author = postAuthor;
          resolve(); // complete the current promise
      }
    });

    promises.push(promise);
});

Promise.all(promises).then(() => {
  res.render('index', {
    posts: myPosts
  });
  res.end();
});

【讨论】:

  • 您已经完成了 90%,然后您没有将 res.render() 放入 Promise.all() 回调中。
【解决方案3】:

您可以通过两种方式做到这一点,您可以制作/使用 Promise 或使用计数方法。

计数方法:

var numComplete = 0;
var done = function() {
    if(numComplete >= myPosts.length) {
        // Code to run once finished
    }
};

myPosts.forEach(function(post) {
    getPostAuthor(post.authorID, function(postAuthor) {
        post.author = postAuthor;
        numComplete++;
        done();
    }
});

【讨论】:

    【解决方案4】:

    您可以使用像 Async 这样的第三方库。

    例子:

    import each from 'async/each';
    
    var elements = [1, 2, 3, 4, 5, 6];
    
    each(elements, function(el, next) {
        console.log('Processing element ' + el);
        callAsyncFunction(next); //your async function should accept a callback
    }, function(err){
        //this is your ending function. It'll be called after all elements have been processed
        if( err ) {
            console.log('A file failed to process');
        } else {
            console.log('Async processing is finished.');
        }
    });
    

    您的代码应如下所示:

    each(myPosts, function(post, next) {
        getPostAuthor(post.authorID, function(postAuthor) {
            post.author = postAuthor;
            next()
        });
    }, function(err) {
        if (!err) {
            res.render('index', {
                posts: myPosts
            });
            res.end();
        }
    });
    

    【讨论】:

      【解决方案5】:

      你可以试试async/awaitfor loop

      const sleep = timeout => new Promise(resolve => setTimeout(() => resolve(), timeout));
      const myPosts = [1,2,3];
      
      const fetchPosts = async () => {
        for (let post_id of myPosts) {
          await sleep(1000); // simulate fetch post
          console.log('post:', post_id);
        }
      
        console.log('done!');
      };
      
      fetchPosts();

      【讨论】:

        【解决方案6】:

        使用 async.eachOf 遍历数组并应用异步函数:

         async.eachOf(myPosts, function(post, it, callback){
        
            // apply async function on each element
            getPostAuthor(post.authorID, function(postAuthor) {
                post.author = postAuthor;
                return callback();
            });
        
         }, function(err){
            // final callback when flow is finished
            res.render('index', {
                 posts: myPosts
            });
            return res.end();
         });
        

        查看异步文档:https://caolan.github.io/async/docs.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-06
          • 2019-12-01
          • 1970-01-01
          • 2021-05-25
          • 2020-08-08
          • 2014-05-12
          • 1970-01-01
          相关资源
          最近更新 更多