首页 > 解决方案 > 递归获取请求

问题描述

我正在尝试编写一个递归获取函数。我正在调用一个接受名称参数并返回它们的端点和一个类似这样role的数组:direct-subordinates

{
    role: "CEO",
    direct-subordinates: [ "john smith", "bob jones" ]
}

然后我想再次调用该函数为每个下属请求相同的数据。

这是我的代码:

export const fetchEmployee = async (name) => {
  let url = `https://url.com/to/employees/endpoint/${name}`
  let req = await fetch(url)
  let json = await req.json()
  return json
}

export const recursiveFetchEmployees = async (initialName) => {
  let json = await fetchEmployee(initialName)
  const role = json[0]
  const subordinates = json[1]
  if (subordinates) {
    return {
      name: initialName,
      role: role,
      subordinates: subordinates['direct-subordinates'].map(async (subordinate) => {
        let result = await recursiveFetchEmployees(subordinate)
        return result
      }),
    }
  } else {
    return {
      name: initialName,
      role: role,
    }
  }
}

这几乎在调用时有效,recursiveFetchEmployees(employeeName).then((resp) => console.log(resp)) 但结果是:

name: "robert robertson",
role: "CEO",
subordinates: (2) [Promise, Promise],

我该如何更改它,以便该函数沿员工层次结构递归地工作,从而产生如下结果:

{
    name: "robert robertson",
    role: "CEO",
    subordinates: [
        {
            name: "john smith",
            role: "Marketing Manager",
            subordinates: [{
                name: "mary doyle",
                role: "employee",
            }]
        },
        {
            name: "bob jones",
            role: "Development Manager",
            subordinates: [{
                name: "barry chuckle",
                role: "Development Lead",
                subordinates: [{
                    name: "billy bob",
                    role: "Developer",
                }]
            }]
        },
    ],
}

提前感谢您的任何帮助或建议。

编辑/更新

感谢@trincot 给出的好答案,我的问题得到了解决,但它引入了另一个问题。我需要检查并过滤返回结果中的重复项。我介绍了一个uniqueNameArray用空数组初始化的 a ,并且在每次调用时,initialName如果它在数组中不存在,它会添加当前参数的名称。这是我的代码:


export const recursiveFetchEmployees = async (initialName, uniqueNameArray = []) => {
  if (!uniqueNameArray.includes(initialName)) {
    uniqueNameArray.push(initialName)
    let json = await fetchEmployee(initialName)
    const role = json[0]
    const subordinates = json[1]
    if (subordinates) {
      return {
        name: initialName,
        role: role,
        subordinates: await Promise.all(
          subordinates['direct-subordinates'].map(
            (subordinate) => subordinate && recursiveFetchEmployees(subordinate, uniqueNameArray)
          )
        ),
      }
    } else {
      return {
        name: initialName,
        role: role,
      }
    }
  }
}

不幸的是,当有重复时,它仍然会在 map 函数中被调用,从而产生一个subordinates如下所示的数组:

    {
       name: "bob jones",
       role: "Development Manager",
       subordinates: [
           {
               name: "barry chuckle",
               role: "Development Lead",
                   subordinates: [{
                      name: "billy bob",
                      role: "Developer",
                   }]
           },
           {
               name: "james jameson",
               role: "Development Lead",
                   subordinates: [{
                      name: "joey joe joe junior",
                      role: "Developer",
                   }]
            },
            undefined,   // <-- This is where there was a duplicate
         ]
     },

有没有办法从承诺列表中省略它?据我所知,我上面所做的应该做到这一点,所以我不确定为什么它仍然返回未定义的响应。

一如既往,感谢任何帮助,谢谢!

标签: javascriptjsonasynchronousasync-awaites6-promise

解决方案


.map(async ...返回一个 Promise 对象数组并不奇怪,因为async函数总是返回一个 Promise。

你可以Promise.all在这里使用:

subordinates: await Promise.all(
    subordinates['direct-subordinates'].map(recursiveFetchEmployees)
),

另请注意,您可以将recursiveFetchEmployees作为回调参数传递给.map. 无需创建该包装函数。


推荐阅读