#reactjs #react-native #async-await #es6-promise #for-await
#reactjs #реагировать-родной #асинхронный-ожидание #es6-обещание #для-ожидание
Вопрос:
Я использую цикл for await для перебора массива и сопоставления значения внутри firestore cloud, но, к сожалению, результат не соответствует ожиданиям; вот мой код
(async () => {
for await (const element of array) {
firestore().collection('users').where('value', '==', element).get()
.then(async snapshot () => {
setvalue(snapshot.data())
}
setIsLoading(false);
}();
Когда я запускаю приложение в эмуляторе, и массив содержит 2 элемента, он просто выдает мне результат, как и ожидалось, но когда массив превышает 40 или n-е число, результат обновляется не так, как ожидалось, и через несколько минут отображается ожидаемый результат.
Я просто хочу обновить состояние isLoading false, когда цикл for await завершит свой цикл, а также код внутри блока цикла завершит проверку firebase, а затем только setIsLoading(false)
Комментарии:
1. Выполнение сетевых запросов внутри цикла — плохая идея. Очень, очень медленно. Пакетируйте его в один запрос.
Ответ №1:
Вместо for await
этого используйте await
для своей get()
функции.
Это должно сработать!
(async () => {
for (const element of array) {
const snapshot = await firestore().collection('users').where('value', '==', element).get();
setvalue(snapshot.data());
}
setIsLoading(false);
}();
Ответ №2:
(async () => {
const allValues = await Promise.all(array.map( item => {
return firestore().collection('users').where('value', '==', element).get()
.then(async snapshot () => {
//do something
return value
}
})
console.log('allValues', allValues)
setIsLoading(false);
}();
Вы можете рассмотреть возможность использования Promise.all и дождаться завершения всех операций.
Как было рекомендовано ранее, лучше разбить его на куски и вместо этого использовать where(‘value’,’in’, array) .
Обновление — использовать для цикла (я разбиваю их на этапы, чтобы вы могли изменять их для собственного использования)
//create a function
const myJob = async() => doSomething
//empty array to hold all the async jobs.
let myPromises = []
//for loop to do whatever u want.
for ( var i = 0; i < 10; i ) {
myPromises.push(myJob(i));
}
//now call Promise.all with the array of jobs
const myResults = Promise.all(myPromises);
Комментарии:
1. Да, но если размер массива превысит 10, это не сработает, я также попробовал с помощью array.slice, но результат тот же
2. Могу ли я узнать, чего вы пытаетесь достичь? Что я вижу, вы получаете значения и ничего не делаете. В большинстве случаев использования в реальном мире вам не нужно перебирать все записи таким образом. Если вы делаете это таким образом, тогда необходимо пересмотреть дизайн ваших данных
3. Чего я пытаюсь достичь, так это того, что существует массив электронных писем из более чем 50, и я хочу просмотреть электронные письма и сопоставить документ пользователей, где email == электронное письмо, которое находится в массиве, и если есть документ, то есть хук useState, который можно обновить, используя previousstateметод и значение добавляются в этом состоянии…
4. разделите их на массивы по 10 и используйте значение where в цикле. Таким образом , вы только звоните . где 5 раз, а не 50 раз. Не имеет значения, является ли это firebase или любой другой базой данных. Вызов API 50 раз подряд означает 50 вызовов базы данных, 50 сетевых накладных расходов и т. Д. С каждым вызовом он становится экспоненциально медленнее.
5. Ценю ваш ответ, я уже пробовал это, но при использовании предложения in я сталкиваюсь с тем, что при наличии 50 электронных писем цикл for выполняется как ожидалось, но код, который устанавливает загрузку (false), срабатывает до того, как все 5 записей находятся в асинхронном запросе…