【问题标题】:How to have concurrent async calls in a nested map function如何在嵌套映射函数中进行并发异步调用
【发布时间】:2020-03-08 17:04:00
【问题描述】:

我有一个对象,它有一个嵌套的对象数组,它还有另一个嵌套的对象数组。我有一个异步函数来检查它们是否有效。我希望它同时运行,但我想等待所有的承诺返回。现在我有:

function validate(userId): Promise<User> {
  let user = await this.userRepo.findById(input).catch(err => this.handleNotExistent(err))
  let friends = user.friends || []
  await Promise.all(friends.map(async friend => {
    let validFriend = await this.friendRepo.findById(friend.id).catch(err => this.handleNotExistent(err))
    if (validFriend.name != friend.name || validFriend.age != friend.age) {
      this.handleInvalidRequest()
    }
    else {
      let friendOfFriends = friend.friendOfFriends || []
      return await Promise.all(friendOfFriends.map(async friendOfFriend => {
        let validFOF = await this.FOFRepo.findById(friendOfFriend.id).catch(err => this.handleNotExistent(err))
        if (validFOF.name != friendOfFriend.name) {
          this.handleInvalidRequest()
        }
        else {
         return validFOF
        }   
     }
   }
}


我怎样才能重写它,以便它按顺序运行(您需要先找到 validFriend 才能查找他们的friendOfFriend,但是所有映射的项目都同时运行?

【问题讨论】:

  • 现在,两个映射的 Promise 已经在并行运行。 1) friends 上的顶级 Promise.all,以及 2) friendOfFriends 上的嵌套 Promise.all。并且您的其他条件也得到满足:“先找到validFriend,然后才能查找他们的friendOfFriend”。要记住的一件事是函数签名显示返回 Promise&lt;User&gt;,但目前没有返回任何内容。
  • 对不起,我排除了最后的return语句。所以所有的朋友都是同时验证的,而不是顺序验证?
  • @VikramKhemlani 是的,它正在同时运行。看起来这段代码没有任何问题。你可以把!= 变成!==
  • 这完全取决于您想要的最终输出。就目前而言,您最终会得到一个包含friends_of_friends 数组的数组,但没有尝试过滤掉任一级别的无效朋友。
  • 返回一个 validated 朋友的数组是有意义的,每个朋友都有一个包含 validated 朋友数组的属性(即每个朋友的经过验证的朋友)。如果这是您想要的,那么您需要为每个地图做两件事(1)如果有效则返回friend,如果无效(不要抛出)则返回错误(例如null),然后(2)过滤映射数组以清除空值,只留下有效的朋友。您还需要将每个朋友的经过验证的朋友附加为原始朋友的属性。

标签: javascript typescript promise async-await


【解决方案1】:

你有两个问题:

  1. 要解压的嵌套结构
  2. 如何等待多个承诺

如果您可以使代码独立并可在 TypeScript 操场上运行(显然,您必须将其制作为真实的简化版本),那将是理想的,因为这样会更容易显示你解开它。

但在精神上,我会采取的第一种方法是:

async function validate(userId): Promise<User> {
  ...
  let friends = await findFriendsAndTheirFriends(userId)
  return Promise.all(friends.map(validateFriend))
}

第一个函数findFriendsAndTheirFriends()(当然,你必须这样写)接受给定的用户 ID 并返回朋友及其朋友的列表。第二个函数接受每个朋友userId 并返回一个将验证该朋友的承诺。

但我不认为你有两个级别的朋友的方式是好的。除了难以阅读之外,它还非常不灵活,几乎无法调试。

您最好将其转换为某种图形问题,在其中搜索与您的节点(您的用户)相距

这种方法的美妙之处在于它仍然可以使用上面的代码,只是 findFriendsAndTheirFriends() 函数会在后台进行图形搜索。

【讨论】:

  • 谢谢安德鲁!但是找朋友和他们的朋友不是同一个映射函数吗? (通过循环和他们的朋友找到朋友)。如果我返回一个对象数组,它有一个嵌套数组(朋友和朋友的朋友),我会两次抛出相同的信息,首先是查找,然后是验证?另外,您是否有任何指向图形函数的链接,我似乎找不到任何东西,而且我使用的是关系数据库 postgres,所以没有图形。
  • @VikramKhemlani,正如问题中所写,第一级和第二级验证之间存在三个区别:(i)未验证朋友存储的用户属性.friends vs .friendOfFriends。 (ii) 回购“friendRepo”与“FOFRepo”。 (iii) 好友属性已验证,.name &amp;&amp; .age.name。如果你想通过相同的函数找到friends和friends_of_friends,则需要在整体设计中消除或消除这些差异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 2018-04-02
相关资源
最近更新 更多