Аксиомы и зацикленные обещания

#reactjs #typescript #promise #axios

Вопрос:

У меня проблема с циклом на оси GET запроса, и я не могу понять, почему.

 const [ state, setState ] = useState<any[]>([]);

ids.forEach((id) => {
    getData(id)
        .then((smth: Map<string, any>[]) => getNeededData(smth, id));
});
console.log(JSON.stringify(state));
 

и getData (getNeededData-это только выбор параметров):

 export const getData= async (id: string) => {
const response = await Axios.get(`/rest/${id}`)
    .then((res: { data: any; }) => res.data);
return response;
};
 

У меня должно быть 2 ответа (это 2 идентификатора в переменной «идентификаторы»), но у меня есть первый, второй, первый, второй, первый, и это в цикле.
Почему это так работает?
Что я могу изменить, чтобы исправить это?

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

1. Вы хотите, чтобы эти запросы выполнялись последовательно или параллельно?

2. Это запрос максимум на 5, так что это не большая разница, но мне любопытно, как переключаться между последовательным и параллельным? 🙂

Ответ №1:

Поместив это forEach на верхний уровень функции компонента, вы запускаете его каждый раз, когда функция вызывается с помощью React, чтобы отобразить ее содержимое, что происходит при изменении состояния. Код, который вы показали, не задает состояние, но я предполагаю, что это делает ваш настоящий код.

Чтобы сделать это только при первом монтировании компонента, оберните его useEffect обратным вызовом с пустым массивом зависимостей:

 const [ state, setState ] = useState<any[]>([]);

useEffect(() => {
    ids.forEach((id) => {
        getData(id)
            .then(/*...*/);
    });
}, []);
 

Если все результаты собираются в state массив, вы, вероятно, захотите использовать map и Promise.all объединить их все и выполнить с ними одно изменение состояния, например:

 const [ state, setState ] = useState<any[]>([]);

useEffect(() => {
    Promise.all(
        ids.map((id) => {
            return getData(id).then(/*...*/);
        })
    )
    .then(allResults => {
        // Use `allResults` to set state; it will be an array in the same order
        // that the `id` array was in
    })
    .catch(error => {
        // handle/report error
    });
}, []);