Асинхронный JavaScript никогда не был легким. Некоторое время мы использовали обратные вызовы. Тогда мы использовали обещания. И теперь у нас есть асинхронные функции.
Асинхронные функции облегчают написание асинхронного JavaScript, но он поставляется со своим собственным набором gotchas, что делает жизнь трудной для начинающих.
В этой серии из 2 частей я хочу поделиться всем, что вам нужно знать об асинхронных функциях.
Асинхронные функции содержат async
ключевое слово. Его можно использовать в обычном объявлении функции:
async function functionName (arguments) {
// Do something asynchronous
}
Вы также можете использовать его в функции стрелки.
const functionName = async (arguments) => {
// Do something asynchronous
}
Это не имеет значения, что вы return
. Возвращаемое значение всегда будет обещанием.
const getOne = async _ => {
return 1
}
const promise = getOne()
console.log(promise) // Promise
Примечание: Вы должны знать, что такое обещания JavaScript и как их использовать, прежде чем двигаться дальше. В противном случае, это начнет запутываться. Эта статьяпоможет вам ознакомиться с обещаниями JavaScript.
Когда вы вызываете обещание, вы обрабатываете следующий шаг в then
вызове, как это:
const getOne = async _ => {
return 1
}
getOne()
.then(value => {
console.log(value) // 1
})
await
Ключевое слово позволяет дождаться разрешения проблемы. После разрешения promise возвращает параметр, переданный в then
вызов.
const test = async _ => {
const one = await getOne()
console.log(one) // 1
}
test()
Там нет необходимостиawait
, прежде чем вернуть обещание.Вы можете возвратить обещание сразу.
(Если вы return await
что-то, вы решить первоначальное обещание в первую очередь. Затем создайте новое обещание из разрешенного значения. return await
эффективно ничего не делает. Нет необходимости в дополнительном шаге).
// Don't need to do this
const test = async _ => {
return await getOne()
}
test()
.then(value => {
console.log(value) // 1
})
// Do this instead
const test = async _ => {
return getOne()
}
test()
.then(value => {
console.log(value) // 1
})
Примечание: Если вам не нужноawait
, вам не нужно использовать асинхронную функцию. Приведенный выше пример можно переписать следующим образом:
// Do this instead
const test = _ => {
return getOne()
}
test()
.then(value => {
console.log(value) // 1
})
Если обещание приводит к ошибке, вы обрабатываете его с помощью catch
вызова, как это:
const getOne = async (success = true) => {
if (success) return 1
throw new Error('Failure!')
}
getOne(false)
.catch(error => console.log(error)) // Failure!
Если вы хотите обработать ошибку в асинхронной функции, необходимо использовать try/catch
вызов.
const test = async _ => {
try {
const one = await getOne(false)
} catch (error) {
console.log(error) // Failure!
}
}
test()
При наличии нескольких await
ключевых слов обработка ошибок может стать некрасивой…
const test = async _ => {
try {
const one = await getOne(false)
} catch (error) {
console.log(error) // Failure!
}
try {
const two = await getTwo(false)
} catch (error) {
console.log(error) // Failure!
}
try {
const three = await getThree(false)
} catch (error) {
console.log(error) // Failure!
}
}
test()
Есть лучший способ.
Мы знаем, что асинхронные функции всегда возвращают обещание. Когда мы вызываем обещание, мы можем обрабатывать ошибки в catch
вызове. Это означает, что мы можем обрабатывать любые ошибки из нашей асинхронной функции путем добавления .catch
.
const test = async _ => {
const one = await getOne(false)
const two = await getTwo(false)
const three = await getThree(false)
}
test()
.catch(error => console.log(error)))
Примечание: catch
метод Promise позволяет поймать только одну ошибку.
await
блокирует JavaScript от выполнения следующей строки кода, пока обещание не будет выполнено. Это может привести к непреднамеренному замедлению выполнения кода.
Чтобы показать это в действии, нам нужно создать задержку перед разрешением обещания. Мы можем создать задержку с sleep
функцией.
const sleep = ms => {
return new Promise(resolve => setTimeout(resolve, ms))
}
ms
число миллисекунд ожидания перед разрешением. Если вы перейдете 1000
вsleep
, JavaScript будет ждать одну секунду, прежде чем решить обещание.
// Using Sleep
console.log('Now')
sleep(1000)
.then(v => {
console.log('After one second')
})
СкажемgetOne
, требуется одна секунда, чтобы решить. Чтобы создать эту задержку, мы переходим 1000
(одна секунда) в sleep
. После того как одна секунда проходила и sleep
обещание разрешает, мы возвращаем значение 1.
const getOne = _ => {
return sleep(1000).then(v => 1)
}
Если выawait getOne()
, вы увидите, что это занимает одну секунду, прежде getOne
чем решает.
const test = async _ => {
console.log('Now')
const one = await getOne()
console.log(one)
}
test()
Теперь предположим, что вам нужно дождаться трех обещаний. Каждое обещание имеет задержку в одну секунду.
const getOne = _ => {
return sleep(1000).then(v => 1)
}
const getTwo = _ => {
return sleep(1000).then(v => 2)
}
const getThree = _ => {
return sleep(1000).then(v => 3)
}
Если вы await
эти три обещания подряд, вам придется ждать в течение трех секунд, прежде чем все три обещания будут решены. Это не хорошо, потому что мы заставили JavaScript ждать две дополнительные секунды, прежде чем делать то, что нам нужно.
const test = async _ => {
const one = await getOne()
console.log(one)
const two = await getTwo()
console.log(two)
const three = await getThree()
console.log(three)
console.log('Done')
}
test()
Если getOne
getTwo
и getThree
может быть извлечена одновременно, вы сэкономите две секунды. Вы можете получить эти три обещания одновременно Promise.all
.
Есть три шага:
await
массив обещаний сPromise.all
Вот как это выглядит:
const test = async _ => {
const promises = [getOne(), getTwo(), getThree()]
console.log('Now')
const [one, two, three] = await Promise.all(promises)
console.log(one)
console.log(two)
console.log(three)
console.log('Done')
}
test()
Это все, что вам нужно знать об основных асинхронных функциях! Я надеюсь, что эта статья прояснит для вас.
Примечание: эта статья представляет собой измененный отрывок из Learn JavaScript . Если вы нашли эту статью полезной, вы можете проверить ее.
Далее мы рассмотрим асинхронные функции и их поведение в циклах.
Спасибо за чтение. Эта статья помогла вам? Если это так, я надеюсь, что вы подумаете . Вы можете помочь кому-то другому. Большое спасибо!