Зацикливайтесь на массиве идентификаторов и каждый раз делайте отдельный запрос

#javascript #reactjs #es6-promise

Вопрос:

У меня есть конечная точка api, подобная этой, и мне нужно отправить запрос на эту конечную точку.

    api/user-group/{id}/invite/{userId}
 

Проблема, с которой я сталкиваюсь, заключается в том, что моя форма содержит несколько списков, список выбора реакции, который позволяет пользователям выбирать столько групп, сколько они хотят, и поэтому каждый раз, когда пользователь выбирает группу, я сохраняю идентификатор группы в локальном состоянии, но моя конечная точка api принимает только один идентификатор группы. Решение, которое я считаю, слишком зацикливается на идентификаторах групп и выполняет отдельные запросы. Может ли кто-нибудь подсказать мне, как достичь этого решения, или есть лучшее решение?

Мой Код:

     const AddUserToGroupPage = () => {
       const [currentUserId, setCurrentUserId] = useState('');
       const [GroupIds, setGroupIds] = useState([]); 

       const { inviteUserToGroup } = useUserGroupApi();


      const InviteExistingUser = async () => {
        const body = {};
        const res = await inviteUserToGroup({
          id: groupIds,
          body,
          userId: currentUserId,
        });
        return res;
      };

      const onGroupsSelected = (selected) => {
        if (selected) {
          setGroupIds(selected.map((select) => select.value));
        }
      };

      return (
            <>
              <Select
                name="userGroups"
                label="User Groups"
                placeholder="Select as many groups as you want"
                id="userGroups"
                defaultOptions
                options={groups}
                isMulti
                onSelectChange={onGroupsSelected}
            />
         </>
)
    }
 

Комментарии:

1. Работаю над ответом, но вы, вероятно, захотите взглянуть Promise.all на это.

2. Спасибо, что помогли мне. Мне нужно больше разбираться в Обещаниях.

3. См.Ответ ниже. Кроме того, я думаю, что у вас может быть небольшая опечатка с заглавной буквы в GroupIds vs groupIds .:)

Ответ №1:

Я думаю, что вы можете достичь того, чего хотите, вот так:

 const InviteExistingUser = async () => {
    const body = {};
    return await Promise.all(
        groupIds.map((groupID) => {
            return inviteUserToGroup({
                body,
                id: groupID,
                userId: currentUserId,
            });
        }),
    );
};
 

В этом коде вызов to groupIds.map() вернет список обещаний, каждое из которых соответствует возвращаемому значению из вызова to inviteUserToGroup (один результат для каждого идентификатора группы).

Затем вы можете передать этот список Promise.all , который возвращает обещание, которое преобразуется в список результатов. Таким образом, в основном вы переходите от Promise<result>[] (списка обещаний) к Promise<result[]> (обещанию для списка).

Затем вы можете await это пообещать, и в этот момент вы получите список результатов для всех звонков inviteUserToGroup .

Ответ №2:

У вас есть 3 варианта:

1. каждый раз выполняйте один запрос

 GroupIds.forEach(g => {
  const body = {};
  const res = await inviteUserToGroup({
    id: g.id,
    body,
    userId: currentUserId,
  });
  // save response
  setGroupsInfo(prev => [...prev, res]
}) 

2. выполняйте все запросы вместе

 const requests = GroupIds.map(g => {
  return inviteUserToGroup({
    id: g.id,
    body,
    userId: currentUserId,
  });
})

Promise.all(requests).then(resArray => {
  setGroupsInfo(resArray)
}) 

3. запустите кучу (может быть, 5) запросов и подождите, пока они не закончатся, а затем запустите еще один и так далее..

 // take 5 each time
for(let i = 0; i < GroupIds.length; i  = 5){
  const subGroupsIds = GroupIds.slice(i, i   5);
  
  // fire 5 requests
  const requests = subGroupsIds.map(g => {
    return inviteUserToGroup({
      id: g.id,
      body,
      userId: currentUserId,
    });
  })

  // wait for the 5 requests
  const resArr = await Promise.all(requests);
  setGroupsInfo(prev => [...prev, ...resArr]);
} 

второй вариант наихудший, так как у вас может быть так много групп, и вы не сможете запросить их все одновременно.

3-й вариант является оптимальным, но его реализация не является прямолинейной.

первый вариант прост и прост, но для большого количества групп будет медленным.