Node.js
Асинхронный / Await
Поиск…
Вступление
Async / await - это набор ключевых слов, который позволяет обрабатывать асинхронный код процедурным образом, не полагаясь на обратные вызовы ( callback hell ) или bind-chaining ( .then().then().then()
).
Это работает, используя ключевое слово await
чтобы приостановить состояние функции async, до разрешения обещания, и используя ключевое слово async
для объявления таких функций async, которые возвращают обещание.
Async / await доступен по --harmony-async-await
node.js 8 по умолчанию или 7 с использованием флага --harmony-async-await
.
Асинхронные функции с обработкой ошибок Try-Catch
Одной из лучших возможностей синтаксиса async / await является то, что стандартный стиль кодировки try-catch возможен, точно так же, как вы писали синхронный код.
const myFunc = async (req, res) => {
try {
const result = await somePromise();
} catch (err) {
// handle errors here
}
});
Вот пример с Express и prom-mysql:
router.get('/flags/:id', async (req, res) => {
try {
const connection = await pool.createConnection();
try {
const sql = `SELECT f.id, f.width, f.height, f.code, f.filename
FROM flags f
WHERE f.id = ?
LIMIT 1`;
const flags = await connection.query(sql, req.params.id);
if (flags.length === 0)
return res.status(404).send({ message: 'flag not found' });
return res.send({ flags[0] });
} finally {
pool.releaseConnection(connection);
}
} catch (err) {
// handle errors here
}
});
Сравнение обещаний с Async / Await
Функция, использующая обещания:
function myAsyncFunction() {
return aFunctionThatReturnsAPromise()
// doSomething is a sync function
.then(result => doSomething(result))
.catch(handleError);
}
Итак, вот когда Async / Await вводит действие, чтобы получить более чистую нашу функцию:
async function myAsyncFunction() {
let result;
try {
result = await aFunctionThatReturnsAPromise();
} catch (error) {
handleError(error);
}
// doSomething is a sync function
return doSomething(result);
}
Таким образом, ключевое слово async
будет похоже на запись return new Promise((resolve, reject) => {...}
.
И await
похоже , чтобы получить ваш результат в then
обратном вызове.
Здесь я оставляю довольно краткий gif, который не оставит никаких сомнений в виду, увидев его:
Прогресс от обратных вызовов
В начале были обратные вызовы, и обратные вызовы были в порядке:
const getTemperature = (callback) => {
http.get('www.temperature.com/current', (res) => {
callback(res.data.temperature)
})
}
const getAirPollution = (callback) => {
http.get('www.pollution.com/current', (res) => {
callback(res.data.pollution)
});
}
getTemperature(function(temp) {
getAirPollution(function(pollution) {
console.log(`the temp is ${temp} and the pollution is ${pollution}.`)
// The temp is 27 and the pollution is 0.5.
})
})
Но было несколько очень неприятных проблем с обратными вызовами, поэтому мы все начали использовать обещания.
const getTemperature = () => {
return new Promise((resolve, reject) => {
http.get('www.temperature.com/current', (res) => {
resolve(res.data.temperature)
})
})
}
const getAirPollution = () => {
return new Promise((resolve, reject) => {
http.get('www.pollution.com/current', (res) => {
resolve(res.data.pollution)
})
})
}
getTemperature()
.then(temp => console.log(`the temp is ${temp}`))
.then(() => getAirPollution())
.then(pollution => console.log(`and the pollution is ${pollution}`))
// the temp is 32
// and the pollution is 0.5
Это было немного лучше. Наконец, мы нашли async / wait. Который все еще использует обещания под капотом.
const temp = await getTemperature()
const pollution = await getAirPollution()
Останавливает выполнение в ожидании
Если обещание ничего не возвращает, асинхронную задачу можно выполнить, используя await
.
try{
await User.findByIdAndUpdate(user._id, {
$push: {
tokens: token
}
}).exec()
}catch(e){
handleError(e)
}