node.js 中的异步函数完成后如何运行函数?
Posted
技术标签:
【中文标题】node.js 中的异步函数完成后如何运行函数?【英文标题】:How to run a function after an async function completed in node.js? 【发布时间】:2018-01-16 05:14:35 【问题描述】:我想在我的async 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 中的函数
堆栈溢出时这里有数百个重复项。
【参考方案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/await
和for 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
【讨论】:
以上是关于node.js 中的异步函数完成后如何运行函数?的主要内容,如果未能解决你的问题,请参考以下文章