如何在异步操作的每个项目中应用异步函数?

时间:2018-08-15 06:38:45

标签: javascript node.js ecmascript-6

Googled 大量不同的来源,试图连续2天弄清楚,但到目前为止没有任何进展。我很拼命,正在寻找其他人的主意!

我正在尝试在 reduce 函数中应用我编写的异步函数(根据情况可用于promise和回调),因为我正在寻找解析后每个连接对象的值降低了,但是在这一壮举方面我还没有成功。

我想在大量文章 中的每个对象(文章)中应用的功能看起来像 此示例:

renderEngine(
{'author': article.author, 'location': article.location},
'template.xml',
(err, parsedContent) => {
    if (err)
        callback(err, null)
    else
        callback(null, parsedContent)
})

如何通过 reduce 使用这样的功能?

1 个答案:

答案 0 :(得分:0)

reduce与Promises结合使用的一般想法是,每次迭代都要使await达到累加器的分辨率,其中累加器是Promise,一旦上一次迭代完成,它就会解析。这是一个实时片段:

const requests = [1, 1, 1];
const resolveAfterSeconds = function(sec) {
  return new Promise(res => setTimeout(res, sec * 1000))
}

const doBatch = async function() {
  const results = await requests.reduce(async (listP, seconds) => {
    /*
    the reducer function isn't actually running sequentially itself;
    the functions all *start* synchronously immediately,
    but each awaits the resolve of the previous iteration before proceeding
    */
    const list = await listP;
    await resolveAfterSeconds(seconds);
    console.log(`returning ${JSON.stringify(listP)}`);
    // since this is in an async function, this gets automatically converted to a promise:
    return list.concat([seconds]);
  }, []);
  console.log(`done, results ${JSON.stringify(results)}`);
}
doBatch();

对于您的代码,首先将renderEngine调用转换为一个返回Promise的函数,然后在每次迭代中调用该函数非常简单:

const getRender = renderArg => new Promise((resolve, reject) => {
  renderEngine(renderArg, (err, parsedContent) => {
    if (err) return reject(err);
    resolve(parsedContent);
});

const parseArticles = articles => articles.reduce(async (articlesSoFarP, { author, location }) => {
  const articlesSoFar = await articlesSoFarP;
  const renderedArticle = await getRender({ author, location });
  return [...articlesSoFar, renderedArticle];
}, []);

但是,如果您使用for循环代替,则阅读代码可能会更加清晰:

const parseArticles = async (articles) => {
  const parsedArticles = [];
  for (const { author, location } of articles) {
    const renderedArticle = await getRender({ author, location });
    parsedArticles.push(renderedArticle);
  }
  return parsedArticles;
};