Я подумал, что отвечу на это прежде всего потому, что асинхронность в Javascript раньше приводила меня в замешательство, и внезапно это прекратилось, поэтому я надеюсь, что эта аналогия может помочь вам в этом.
У вас есть асинхронное событие.Это может быть что угодно, получение чего-либо с сервера, выполнение чего-либо в браузере, что требует времени, обучение модели машинного обучения (!), Выполнение функции или метода, использующего setTimeout и т. Д.
Красота Javascriptи основная причина того, что он работает так хорошо для браузера, заключается в том, что он использует поток процессора, на котором он работает, очень умным способом, который предотвращает блокировку потока процессами, которые занимают время (как те, что упомянуты выше)
Многие другие языки, например Ruby, работают более чем в одном потоке.Можно использовать сервисные работники для запуска процессов в нескольких потоках в javascript, но это выходит за рамки этого ответа!
Асинхронная природа цикла событий JS позволяет потоку «выключаться» и что-то делатьв то время как он ожидает завершения процесса.
Проблема с этим с точки зрения программирования заключается в том, что в коде возможно, что что-то, основанное на результате блокирующего события, получит 'undefined'в результате события, если оно не ожидает завершения события, прежде чем попытается использовать его результат.Возьмите этот фрагмент кода ниже
let scopedVariable
console.log('the code has started')
setTimeout(() => {
scopedVariable="I am the result of some async process"
}, 5000);
console.log(scopedVariable)
Когда код достигает журнала консоли, setTimeout еще не завершен.Так как setTimeout устанавливает scopedVariable только после его завершения, переменная не определена, когда мы регистрируем ее
, если, однако,
Мы завершим тайм-аут в обещании, которое мы можем ожидать, пока он не получит ответ callback (первый аргументобещание), и код будет «приостанавливаться», пока обещание не достигнет обратного вызова разрешения, прежде чем продолжить.
Когда мы ожидаем обещание и setTimeout завершается, функция разрешения устанавливает переменную, так что когда мы консоль регистрируем еесодержит значение из обещания
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
const container = async () => {
const result = await asyncEvent
console.log(scopedVariable)
}
container()
Вы можете использовать await и .then взаимозаменяемо
Например, мы можем пойти:
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
const container = async () => {
asyncEvent.then(() => console.log(scopedVariable))
}
container()
еще раз, код будет приостановленв .then, а затем продолжить, когда обещание asyncEvent разрешилось.
Фактически, если мы используем .then, нам не нужно заключать его в асинхронную функцию, чтобы мы могли переписать его следующим образом
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
asyncEvent.then(() => console.log(scopedVariable))
Самое замечательное в .then заключается в том, что сопровождающий .catch позволяет вам отследить любые ошибки, вызванные асинхронным событием (например, еслиng что-то с сервера, когда есть ошибка).Для асинхронного ожидания вам нужно обернуть потенциально опасные функции в try catch.
Чтобы использовать ожидание, вы должны быть внутри асинхронной функции (отсюда и функция асинхронного контейнера выше).Это не обязательно с .then, но цепочки .then и .catch могут сделать ваш код неопрятным.
Надеюсь, это поможет!