简体   繁体   English

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

[英]How to apply an asynchronous function into each item of a reduce operation?

Googled a ton of different sources, tried to figure it out for 2 days in a row, but nothing worked as expected until now. Google搜索了许多不同的来源,试图连续2天弄清楚,但到目前为止没有任何工作能像预期的那样工作。 I'm a bit desperate and looking for other mind's ideas! 有点绝望,正在寻找其他人的想法!

I'm trying to apply an asynchronous function I've written (that works with both promises and callbacks depending on the situation) inside a reduce function since I'm looking for the reduced value of the objects concatenated after each one is parsed, but I'm not succeeding on this feat yet. 我正在尝试将我编写的异步函数(根据情况可与promise和回调一起使用)应用到reduce函数中,因为我要在解析每个对象后寻找级联对象的降低值,但是我目前还没有成功。

The function I want to apply in each object(article) of the big array of articles 我想在大量文章的每个对象(文章)中应用的功能 looks like 看起来像 this sample: 这个样本:

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

How can one use a function like this with reduce ? 怎样用reduce来使用这样的功能?

The general idea of using reduce with Promises is for each iteration to await the resolution of the accumulator, where the accumulator is the Promise that resolves once the previous iteration finishes. 与Promises一起使用reduce的一般想法是让每个迭代await累加器的分辨率,其中累加器是一个Promise ,它会在上一个迭代完成后解决。 Here's a live snippet: 这是一个直播片段:

 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(); 

For your code, it would probably be useful to first transform the renderEngine call into a function that returns a Promise , and then it's pretty straightforward to call that function on each iteration: 对于您的代码,首先将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];
}, []);

But, it would probably be a lot clearer to read the code if you used a for loop instead: 但是,如果您使用for循环来代替,则阅读代码可能会更加清晰:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM