Тогда использование предыдущего Generator+conuggets.capable/post/684490…
Продолжаем рассказывать о методе js асинхронной обработки async await (то есть синтаксическом сахаре Генератора)
async — это сокращение от «асинхронный», async используется для объявления того, что функция является асинхронной, а await используется для ожидания завершения асинхронного метода, await может появляться только в асинхронных функциях.
Также используйте пример чтения файла из предыдущей статьи, переписанный здесь как
let bluebird = require('bluebird');
let fs = require('fs');
let read = bluebird.promisify(fs.readFile);
//await 命令后面的 Promise 对象,运行结果可能是 //rejected,所以最好把 await 命令放在 try...catch 代码块中。
async function r(){
try{
let content1 = await read('1.txt','utf8');
let content2 = await read(content1,'utf8');
return content2;
}catch(e){
console.log('err',e)
}
}
r().then(function(data){
console.log('data',data);
},function(err){
console.log('err1',err);
})
Async await очень похож на генератор, то есть замените звездочку (*) функции Generator на async, а yield замените на await
Но асинхронная функция улучшает функцию Генератора:
1. Встроенный исполнитель: выполнение функции генератора должно зависеть от исполнителя, поэтому существует библиотека функций co, а асинхронная функция имеет свой собственный исполнитель, то есть выполнение асинхронной функции является именно то же, что и обычная функция.
2. Лучшая семантика: async и await имеют более четкую семантику, чем звездочки и yield. async означает, что в функции есть асинхронная операция, а await означает, что следующему выражению необходимо дождаться результата.
3. Более широкая применимость: соглашение библиотеки функций co, за командой yield может следовать только функция Thunk или объект Promise, в то время как за командой await асинхронной функции может следовать объект Promise и значения примитивного типа (числовые , строковые и логические значения). , но это эквивалентно синхронной операции)
Асинхронная функция — это очень новая синтаксическая функция, и она принадлежит не ES6, а ES7. В настоящее время он все еще находится на стадии предложения, но транскодеры Babel и regenerator уже поддерживаются и могут использоваться после перекодирования.
Роль асинхронности
асинхронные функции отвечают за возврат объекта Promise.
Если вы возвращаете литерал в асинхронной функции, async инкапсулирует литерал в объект Promise через Promise.resolve();
Если асинхронная функция не имеет возвращаемого значения, она вернет Promise.resolve(undefined)
что ждет ждет
Как правило, мы используем await для ожидания завершения асинхронной функции, но, согласно грамматике, await ожидает выражения, а результатом выражения является объект Promise или другое значение, так что await может принимать обычные вызовы функций или прямое количество
Если то, что ожидает await, не является объектом обещания, результат следующего выражения — это то, чего он ожидает;
Если это объект обещания, await заблокирует следующий код, дождется разрешения объекта обещания и получит значение разрешения как результат выражения ожидания.
Хотя ожидание заблокировано, ожидание находится в асинхронном режиме, асинхронный не будет блокироваться, вся его внутренняя блокировка инкапсулирована в объект обещания для асинхронного выполнения.
Сценарии использования Async Await
Как и в приведенном выше примере, когда требуется вызов цепочки обещаний, он отражает преимущества Async Await;
Предполагая, что бизнес должен выполняться поэтапно, каждый шаг является асинхронным и зависит от результата выполнения предыдущего шага или даже результата каждого предыдущего шага, вы можете использовать Async Await для его завершения.
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(m, n) {
console.log(`step2 with ${m} and ${n}`);
return takeLongTime(m + n);
}
function step3(k, m, n) {
console.log(`step3 with ${k}, ${m} and ${n}`);
return takeLongTime(k + m + n);
}
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time1, time2);
const result = await step3(time1, time2, time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
Если вы используете обещания для реализации
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => {
return step2(time1, time2)
.then(time3 => [time1, time2, time3]);
})
.then(times => {
const [time1, time2, time3] = times;
return step3(time1, time2, time3);
})
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
Видно, что с промисами передача параметров очень проблематична.
В следующем примере указывается, через сколько миллисекунд будет выведено значение.
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value)
}
asyncPrint('hello world', 50);
Уведомление
Объект Promise после команды await может быть отклонен, поэтому команду await лучше поместить в блок кода try...catch или добавить обратный вызов catch в Promise после await
await read('1.txt','utf8').catch(function(err){
console.log(err);
})
await может появляться только в асинхронных функциях, при использовании в обычных функциях будет сообщено об ошибке
async function dbFuc(db) {
let docs = [{}, {}, {}];
// 报错
docs.forEach(function (doc) {
await db.post(doc);
});
}
Приведенный выше код сообщит об ошибке, поскольку в обычных функциях используется await. Однако, если параметр метода forEach изменить на асинхронную функцию, также возникает проблема.
async function dbFuc(db) {
let docs = [{}, {}, {}];
// 可能得到错误结果
docs.forEach(async function (doc) {
await db.post(doc);
});
}
Приведенный выше код может работать неправильно, поскольку три операции db.post будут выполняться одновременно, то есть одновременно, а не последовательно. Правильный способ написать это использовать цикл for.
async function dbFuc(db) {
let docs = [{}, {}, {}];
for (let doc of docs) {
await db.post(doc);
}
}
Если вы действительно хотите, чтобы несколько запросов выполнялись одновременно, вы можете использовать метод Promise.all.
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc));
let results = await Promise.all(promises);
console.log(results);
}
// 或者使用下面的写法
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc));
let results = [];
for (let promise of promises) {
results.push(await promise);
}
console.log(results);
}
Суммировать
Использование async/await с промисами может обрабатывать асинхронные процессы путем написания кода, который выглядит синхронным, улучшая краткость и читабельность кода.
Преимущества асинхронного ожидания:
1. Решить проблему ада обратного звонка
2. Поддержка одновременного выполнения
3. Вы можете добавить возвращаемое значение return xxx;
4. Вы можете добавить в код try/catch для отлова ошибок
использованная литература
1,сегмент fault.com/ah/119000000…