【问题标题】:Resolve a promise nested inside an array of objects解决嵌套在对象数组中的承诺
【发布时间】:2021-03-12 17:02:37
【问题描述】:

我有一个从数据库中获取的对象数组。

const users = await User.findAll();

对于他们每个人,我想调用一个异步函数user.getDependency() 来获取另一个相关表,并将嵌套在对象中的它转变成这样的最终格式:

[
  User {
    attr1: value,
    attr2: value,
    ...
    Dependency: {
      attr1: value,
      ...
    }
  },
  User {
    ...

等等

现在,我得到了我的问题。我能想到的涉及异步和循环的唯一可能性是 2:

选项 1:映射它们并收回承诺:

  users.forEach((user) => {
    user.dependency= user.getDependency();
  });

有了这个,我在格式方面得到了与预期结果相似的结果,只是我得到的显然不是已解决的东西Dependency: Promise { <pending> },也就是说,所有的承诺都嵌套在数组的每个用户对象中。而且我不知道如何处理它。如何遍历所有用户对象并解决他们内部的这个承诺?

选项 2:返回要在 Promise.all 中解决的承诺

const dependencies = Promise.all(users.map((user) => {
  return user.getDependency();
}));

这给了我一个包含我想要的所有依赖项的单独数组,但就是这样,分开了。我得到一个包含对象用户的数组和另一个包含对象依赖项的数组。

特别困扰我的是,我认为必须有一种简单直接的方法来做到这一点,而我错过了。有人有想法吗?非常感谢

【问题讨论】:

  • 你控制user.getDependency()的代码吗?如果是这样,则让该方法负责将异步结果缓存为用户的道具。那么,您的选项 2 代码就可以了;当 promise.all() 解析时,每个用户都将初始化其依赖项。
  • 很遗憾不是,这是一种sequelize方法。但感谢您的意见!

标签: javascript arrays object asynchronous promise


【解决方案1】:

为了建立一些直觉,这里是你的 forEach 示例,通过推动正确的方向进行转换。

users.forEach((user) => {
  user.getDependency().then(dependency => {
    user.dependency = dependency
  })
})

上面的内容是“对于每个用户,开始获取依赖项,然后在解决后将依赖项添加到用户。”但是,我不认为上述内容非常有用,因为一旦所有依赖项完成获取,您可能希望能够与用户做一些事情。在这种情况下,您可以在 .map 旁边使用 Promise.all

const usersWithResolvedDependencies = await Promise.all(
  users.map(user => user.getDependency().then(dependency => {
    user.dependency = dependency
    return user
  }))
)
// do stuff with users

我应该提到我写了一个简化异步的库,当然也可以用来简化这个问题。以下等价于上述。 mapassign 来自我的图书馆,rubico

const usersWithResolvedDependencies = map(assign({
  dependency: user => user.getDependency()
}))(users)

【讨论】:

    【解决方案2】:

    我想最好的方法就是这样做。映射用户,更新每个对象(最好不要突变),并使用 Promise.all

    const pupulatedUsers = await Promise.all(users.map(async (user) => ({
      ...user,
      dependency: await getDependency(user.dependency_id)
      // or something like getDependency
      // function that fires async operation to get needed data
    }));
    

    【讨论】:

      【解决方案3】:

      你是对的,有一种直接的方法来解决这个承诺 由于users 变量不是等待解决的承诺,您应该尝试

      users.then((userList) => {
             // function logic here
      })
      

      then 函数中的userList 应该是可迭代的并包含所需的用户列表

      你也可以处理promise的被拒绝部分,如果查询失败并且promise返回一个错误:

      users.then((error) => {
         // error handling
      })
      

      您应该看一下document 以获取有关处理 Promise 的更多信息,以进一步了解该查询在返回 Promise 时发生了什么

      【讨论】:

        猜你喜欢
        • 2017-10-19
        • 1970-01-01
        • 2021-01-08
        • 1970-01-01
        • 2017-04-04
        • 1970-01-01
        • 2019-10-28
        • 1970-01-01
        • 2018-10-08
        相关资源
        最近更新 更多