#javascript #asynchronous #async-await #promise #es6-promise
Вопрос:
Когда я создаю 3 разных обещания, используя эту функцию:
const setTimer = (num) => {
return new Promise((res, rej) => {
setTimeout(() => {
res(num)
}, 2000);
})
}
а затем запустите их внутри функции async/await:
const func = async () => {
const first = await setTimer(1)
console.log(first);
const second = await setTimer(2)
console.log(second);
const third = await setTimer(3)
console.log(third);
}
func()
Они работают синхронно (один за другим), как и ожидалось.
Затем я создаю 3 разных обещания, используя новое обещание напрямую:
const setTimer1 = new Promise((res, rej) => {
setTimeout(() => {
res(1)
}, 2000);
})
const setTimer2 = new Promise((res, rej) => {
setTimeout(() => {
res(2)
}, 2000);
})
const setTimer3 = new Promise((res, rej) => {
setTimeout(() => {
res(3)
}, 2000);
})
А затем снова запустите эти 3 обещания в функции async/await:
const func1 = async () => {
const first = await setTimer1
console.log(first);
const second = await setTimer2
console.log(second);
const third = await setTimer3
console.log(third);
}
func1()
Теперь они работают асинхронно (параллельно). Пожалуйста, помогите объяснить, почему. Я действительно долго искал, но так и не нашел ответа.
Комментарии:
1. «Теперь они выполняются асинхронно (параллельно)» — нет. они выполняются последовательно; один за другим. Разница в обоих примерах кода заключается в том, что первый создает обещание внутри функции.
2. Обещания «начинаются» при создании экземпляра, а не при первом ожидании. Ваш первый фрагмент создает экземпляр обещания только после завершения предыдущего. Ваш второй фрагмент создает их все, а затем ожидает их.
3.
setTimer()
создаетPromise
при вызове.const setTimerX = new Promise()
создает обещание немедленно.4. Как говорили другие, Обещания начинаются при создании, поэтому в вашем случае они заканчиваются одновременно (хотя и последовательно). Попробуйте установить один на 2000, другой на 3000 и последний на 4000 — вы увидите разницу 🙂
5. @OldGeezer где? В
setTimeout()
или в » новом обещании ()»? Потому что оба этих возвращаемых значения отклоняются и ничего не делают.
Ответ №1:
Проще всего понять разницу, сравнив следующие примеры:
(async () => {
const p1 = new Promise(resolve => setTimeout(resolve, 2000));
const p2 = new Promise(resolve => setTimeout(resolve, 2000));
const p3 = new Promise(resolve => setTimeout(resolve, 2000));
await p1;
console.log(1); // 2 seconds later
await p2;
console.log(2); // 0 seconds later
await p3;
console.log(3); // 0 seconds later
})();
Все Обещания создаются сразу одно за другим, поэтому в то время, когда первое из них готово, все они готовы. Вот почему вы получите 1
, 2
и 3
в вашей консоли одновременно.
Но теперь рассмотрим этот пример:
(async () => {
await new Promise(resolve => setTimeout(resolve, 2000));
console.log(1); // 2 seconds later
await new Promise(resolve => setTimeout(resolve, 2000));
console.log(2); // 2 seconds later
await new Promise(resolve => setTimeout(resolve, 2000));
console.log(3); // 2 seconds later
})();
На этот раз второе обещание будет выполнено после того, как первое будет выполнено, то есть через 2 секунды. То же самое относится и к третьему, ожидающему второго. И вот почему вы получите 1
через 2 секунды, 2
еще через 2 секунды и 3
еще через 2 секунды.
Чтобы понять почему, достаточно знать, что Обещание старается быть как можно более быстрым. Он начинает свою работу, как только он создан. И это хорошо!
Ответ №2:
Ваши последние три объявления не являются функциями. Они назначают каждому обещание, которое выполняется в момент создания каждого из них. Таким образом, они должны быть закодированы так же, как и ваш первый, где обещание создается только при вызове функции:
const setTimer1 = () => new Promise((res, rej) => {
setTimeout(() => {
res(1)
}, 2000);
})
const setTimer2 = () => new Promise((res, rej) => {
setTimeout(() => {
res(2)
}, 2000);
})
const setTimer3 = () => new Promise((res, rej) => {
setTimeout(() => {
res(3)
}, 2000);
})
Затем вам нужно вызвать каждую функцию:
const func1 = async () => {
const first = await setTimer1();
console.log(first);
const second = await setTimer2();
console.log(second);
const third = await setTimer3();
console.log(third);
}
func1()
Необходимые изменения очень незначительны, добавлено всего несколько символов. Сравните с вашим кодом, чтобы увидеть различия.