与条件承诺链反应并在发送调度之前等待它们

React with conditional promises chain and wait for them all before send dispatch

我是新手。我有一个用户列表,该列表在组件安装时获取一次。 在将结果发送到 reducer 之前,它需要在用户列表中循环并从另一个端点获取用户 fullname/title,然后将新的 属性 添加到用户列表对象。 我不知道如何在调用调度之前等待所有承诺(getUserById() 函数)完成。我在这里尝试了解决方案,但失败了:

下面的代码只是为了说明我想要什么:

  const {
    listUsers,
    fetchUserData
  } = useContext(GlobalContext);

  const getUserById = async (userId) => {
    return sp.web.siteUsers.getById(userId).get().then(user => user.Title);
  }

  useEffect(() => {
    sp.web.lists.getById("8C271450-D3F9-489C-B4FC-9C7470594466").items.get()
    .then(userLists => {
      userLists = userLists.map(list => {
        if (list.Person_x0020_ResponsibleId) {
          getUserById(list.Person_x0020_ResponsibleId).then(username => {
            list['Person_Responsible'] = username;  // -> fetch user fullname and title
          })
        } else {  // -> if id is null
          list['Person_Responsible'] = '-';
        }
        return list
      });

      fetchListSuccess(userLists);  // -> dispatch result to reducer
    });
  }, []);

您可以使用 Promise.all 完成此操作。首先,您需要来自第二个 API 调用的一系列承诺。然后我们将这个数组给Promise.all,它会等到他们都解决了。

我使用 async/await 语法重写了。它的工作原理与将 .then 与 promise 一起使用相同,但是当您使用如此复杂的 promise 链时,使用 async/await.

更容易理解
useEffect(async () => {
  const userLists = await sp.web.lists.getById('8C271450-D3F9-489C-B4FC-9C7470594466').items.get();
  const promises = userLists.map(async (list) => {
    if (list.Person_x0020_ResponsibleId) {
      const username = await getUserById(list.Person_x0020_ResponsibleId);
      list.Person_Responsible = username; // -> fetch user fullname and title
    } else { // -> if id is null
      list.Person_Responsible = '-';
    }
    return list;
  });
  await Promise.all(promises);
  fetchListSuccess(userLists); // -> dispatch result to reducer
}, []);

一些注意事项:

  • 您实际上不需要在地图中重新分配 userLists,因为您只是将 属性 添加到现有对象。这将在没有地图的情况下发生。
  • 现在地图正被用于 return 您第二次 API 调用的承诺数组。 Promise.all 使用它来等待所有这些承诺解决。