#javascript #promise #async-await
#javascript #обещаю #async-await
Вопрос:
Правка2: Решение внизу
Я использую chrome-console и пытаюсь вывести выбранные данные, и я получаю желаемый результат, только написав «await» точно в нужном месте, хотя другое решение может сделать это раньше, и я не знаю, почему / как это работает.
solution() — это «официальное» решение из веб-курса, который я делаю. В настоящее время обе функции возвращают одно и то же.В myFunction я пытался написать «await» перед каждой используемой функцией и сделать каждую функцию «асинхронной», но я все еще не могу заменить «await» внутри журнала, хотя другое решение может.
const urls = ['https://jsonplaceholder.typicode.com/users']
const myFunction = async function() {
// tried await before urls/fetch ( make it async)
const arrfetched = urls.map( url => fetch(url) );
const [ users ] = arrfetched.map( async fetched => { //tried await in front of arrfetched
return (await fetched).json(); //tried await right after return
});
console.log('users', await users); // but can't get rid of this await
}
const solution = async function() {
const [ users ] = await Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
console.log('users', users); // none here, so it can be done
}
solution();
myFunction();
Я бы подумал, что «await» работает таким образом, что делает:
const a = await b;
console.log(a); // this doesn't work
то же, что
const a = b;
console.log(await a); // this works
но это не так, и я не понимаю, почему нет. Я чувствую себя как обещание.все это приводит к чему-то неожиданному, поскольку простое написание «await» в объявлении не может сделать то же самое, только после объявления.
Правка 1: это не работает
const myFunction = async function() {
const arrfetched = await urls.map( async url => await fetch(url) );
const [ users ] = await arrfetched.map( async fetched => {
return await (await fetched).json();
});
console.log('users', users);
}
Всем спасибо за помощь Edit2:, я пытался поместить «.toString()» во множество переменных и переключать, где я помещаю «await» в коде, а где нет.
Насколько я понимаю, если я не использую Promise.all, то мне нужно ожидать каждый раз, когда я хочу использовать (как в реальных данных, а не просто использовать) функцию или переменную, которая содержит promises. Недостаточно иметь await только там, где обрабатываются данные, а не дальше.
В приведенной выше правке 1 пользовательские запуски выполняются раньше, чем любое другое ожидание завершено, поэтому независимо от того, сколько ожиданий я записываю, ни одно из них не выполняется. Копирование этого кода в консоль (в моем случае chrome-) прекрасно его демонстрирует:
const urls = [
'https://jsonplaceholder.typicode.com/users',
]
const myFunction = async function() {
const arrfetched = urls.map( async url => fetch(url) );
const [ users ] = arrfetched.map( async fetched => {
console.log('fetched', fetched);
console.log('fetched wait', await fetched);
return (await fetched).json();
});
console.log('users', users);
console.log('users wait', await users);
}
myFunction();
// Output in the order below:
// fetched()
// users()
// fetched wait()
// users wait()
Комментарии:
1. Не ясно, чего вы пытаетесь достичь.
2. Я хочу избавиться от await внутри консоли моей функции следующим образом: console.log(‘users’, пользователи);
3.Вы здесь все слишком усложняете. В вашем «edit1» вы разрешаете массив promises с помощью
async await
, а затем вы сопоставляете этот массив, чтобы фактически притвориться, что удваиваетеawait
то, что уже разрешено. Еслиfetch
возвращает aPromise
, первый.map
должен быть асинхронным. Если.json()
возвращаетPromise
, то второй также должен быть асинхронным. Однако реальноеawait
должно произойти во времяfetch
операции, а не во время чего-либо еще.4. Таким образом, большее количество ожиданий, чем необходимо, может нарушить работу кода, работающего в остальном?
5. Просто чтобы прояснить это (в дополнение к моему ответу): лишнее
await
никогда не вредно (кроме как с точки зрения производительности). Ожидание не-обещания, например,await 'hello'
сначала превратит его в обещание, а затем ожидает этого, так что это эквивалентноawait Promise.resolve('hello')
Ответ №1:
TL; DR: Promise.all
это важно, но в этом нет ничего волшебного. Он просто преобразует массив обещаний в обещание, которое разрешается с помощью массива.
Давайте разберемся myFunction
:
const arrfetched = urls.map( url => fetch(url) );
Это возвращает массив обещаний, пока все хорошо.
const [ users] = arrfetched.map( async fetched => {
return (await fetched).json();
});
Вы разрушаете массив, чтобы получить первый элемент, так что это то же самое, что и это:
const arr = arrfetched.map( async fetched => {
return (await fetched).json();
});
const users = arr[0];
Здесь мы преобразуем массив обещаний в другой массив promises. Обратите внимание, что вызов map
с async
помощью функции всегда приведет к массиву обещаний.
Затем вы перемещаете первый элемент этого массива в users
, так что users
теперь фактически содержит одно обещание. Затем вы ожидаете его перед печатью:
console.log('users', await users);
В отличие от этого, другой фрагмент делает здесь что-то немного другое:
const [ users ] = await Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
Еще раз, давайте разделим деструктурирование:
const arr = await Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
const users = arr[0];
Promise.all
преобразует массив обещаний в одно обещание, результатом которого является массив. Это означает, что после того, как await Promise.all
все в arr
было ожидаемо (вы можете представить await Promise.all
что-то вроде цикла, который ожидает все в массиве). Это означает, что arr
это просто обычный массив (не массив обещаний) и, следовательно, users
его уже ожидают, или, скорее, это никогда не было обещанием в первую очередь, и, следовательно, вам не нужно await
это.
Комментарии:
1. Здесь мы преобразуем массив обещаний в другой массив promises. Обратите внимание, что вызов map с помощью асинхронной функции всегда приведет к появлению массива обещаний. Оооо, итак, моя правка1: const [ users] = await arrfetched.map( … ожидает не пормисы, а массив обещаний, которого ему не нужно ждать!
2. Совершенно верно.
await [Promise.resolve(42), Promise.resolve(24)]
==[Promise.resolve(42), Promise.resolve(24)]
(потому что вы ожидаете массив, который не является обещанием и, следовательно, ничего не делает), ноawait Promise.all([Promise.resolve(42), Promise.resolve(24)])
==[await Promise.resolve(42), await Promise.resolve(24)]
==[42, 24]
Ответ №2:
Возможно, самый простой способ объяснить это — описать, чего достигает каждый шаг:
const urls = ['https://jsonplaceholder.typicode.com/users']
async function myFunction() {
// You can definitely use `map` to `fetch` the urls
// but remember that `fetch` is a method that returns a promise
// so you'll just be left with an array filled with promises that
// are waiting to be resolved.
const arrfetched = urls.map(url => fetch(url));
// `Promise.all` is the most convenient way to wait til everything's resolved
// and it _also_ returns a promise. We can use `await` to wait for that
// to complete.
const responses = await Promise.all(arrfetched);
// We now have an array of resolved promises, and we can, again, use `map`
// to iterate over them to return JSON. `json()` _also_ returns a promise
// so again you'll be left with an array of unresolved promises...
const userData = responses.map(fetched => fetched.json());
//...so we wait for those too, and destructure out the first array element
const [users] = await Promise.all(userData);
//... et voila!
console.log(users);
}
myFunction();
Ответ №3:
Await может использоваться только в асинхронной функции. Await — это зарезервированный ключ. Вы не можете ждать чего-то, если это не асинхронно. Вот почему это работает в консоли.регистрируется, но не в глобальной области видимости.
Комментарии:
1. Итак, когда я пишу что-то вроде в Edit1, это не работает, потому что что-то не асинхронно, хотя я не получаю ошибок?
2. Позвольте мне перефразировать это. Клавиша await должна использоваться в асинхронной функции. Функция map также является функцией, которая будет выполнена, когда сможет. Если вам нужны эти данные, вы можете отобразить эти вызовы в promise.all. Таким образом, функция будет продолжена только в том случае, если все обещания будут выполнены
3. Итак, написав await в консоли. войти Я получаю то же самое, что и await Promise.all, но когда я пишу await внутри объявления переменной, это игнорируется, потому что это не в асинхронной функции?
4. Да, но это похоже на ошибку. Вы должны попытаться избежать этого. Если вы хотите подождать. для обещания используйте правильную функцию для него. Надеюсь, это поможет логике, поскольку она может быть довольно абстрактной.