异步减少返回的承诺

Posted

技术标签:

【中文标题】异步减少返回的承诺【英文标题】:Async reduce returning promises 【发布时间】:2019-12-21 09:22:51 【问题描述】:

我有一个对象数组,我必须为来自异步函数的每个对象添加一个属性

我正在做一个 Array.reduce 来迭代每个元素并只返回一个结果:一个具有新属性的对象数组。

我有这个

const res = await resultOne.reduce(async (users = [], user, i) => 
          let userName;
          try 
            let  name  = await names.getNames(user.id);
            userName = name;
           catch (error) 
            throw error;
          
          delete user.id;
          users.push( ...user, userName );
          return users;
      , []);

但我收到了消息

推送不是用户的功能

这是因为我认为是一个承诺。

如何处理reducemap 中的异步请求

【问题讨论】:

如果你可以使用 Promise 库,你可以使用 bluebird 的 Promise.reduce。 IE。 const res = await Promise.reduce( resultOne, async (users .... @Paulpro 感谢您的回复,问题是我认为在这种情况下添加另一个依赖项是完全必要的,这是我不会在整个项目中重复的内容. 【参考方案1】:

是的,users 是一个承诺。不要use reduce with async functions。您可以在第一行执行await users 之类的操作,但这会非常低效且不合时宜。

使用普通循环:

const users = [];
for (const user of resultOne) 
    const  name  = await names.getNames(user.id);
    delete user.id;
    users.push( ...user, userName: user );

或者,在您可以同时执行所有操作并创建数组的情况下,map 函数与Promise.all 一起使用:

const users = await Promise.all(resultOne.map(async user => 
    const  name  = await names.getNames(user.id);
    delete user.id;
    return  ...user, userName: user ;
));

【讨论】:

感谢您的回复@Bergi,我认为普通循环可以很好地工作并且更具可读性,将通过循环传递的用户数量为数千。但我认为没有办法避免运行所有循环来删除 user.id 并添加 user.name【参考方案2】:

因为它是一个异步函数,所以每次你返回一些东西时,它都会被包装在一个 Promise 中。要解决此问题,您需要将起始数组设置为承诺,然后在每次迭代时等待累加器。

const res = await resultOne.reduce(async (users, user, i) => 
  try 
    return [
      ...await users,
       ...user, userName: await names.getNames(user.id.name) 
    ]
   catch (error) 
    console.log(error)
  
, Promise.resolve([]));

【讨论】:

awaiting users 稍后(在awaiting getNames() 之后)如果其中一个承诺失败,将导致未处理的拒绝警告,请参阅***.com/questions/46889290/… 或 ***.com/questions/45285129/…跨度> @Bergi 我刚刚更新了我的答案。这会阻止/解决您所说的问题吗? 是的,它们现在将按顺序执行。我仍然认为这不是一个好的解决方案,它令人困惑且容易搞砸:-) 感谢@JossClassey 的回复,我一直在关注这种解决方案,但我也同意这不是更易读的选项。

以上是关于异步减少返回的承诺的主要内容,如果未能解决你的问题,请参考以下文章

对从异步函数返回的承诺感到非常困惑

如何让 React Redux 异步操作返回一个承诺?

返回承诺的函数必须是异步的

异步函数返回承诺,而不是值

异步函数返回承诺,而不是值

Javascript - 异步等待和获取 - 返回值,而不是承诺?