Так как писать статью было уже поздно, я был немного сонным и скопировал неправильный код, который был исправлен.
В предыдущем блоге мы объяснили промисы с точки зрения практического использования и интервью (исходный текст см. в разделе "Разговор об обещаниях для вопросов интервью и практического использования"), но метод Promise решает ад обратного вызова, но этот метод полон промисовскихthen()
Метод, если процесс сложный, код будет заполнен целикомthen
, поток кода не может очень хорошо представлять поток выполнения.
Почему асинхронный/ожидающий
В es6 мы можем использовать функцию Generator для управления потоком, как показано в следующем коде:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
Мы можем непрерывно вызывать объект Generator в соответствии сnext()
способ управления потоком функции. Но это не кажется таким смысловым. Поэтому синтаксическая сахарная асинхронная функция функции Generator инкапсулирована в ES6, но определена в es7. Определено ES7async
Функции, наконец, дают JavaScript идеальное решение для асинхронных операций.Async
Функции — это синтаксический сахар для функций-генераторов. использовать ключевые словаAsync
Чтобы указать это, используйте await внутри функции для обозначения асинхронности. По сравнению с генератором улучшение асинхронной функции заключается в следующих моментах: выполнение функции генератора должно зависеть от исполнителя, аAsync()
У функции есть свой исполнитель, а метод вызова такой же, как и у обычных функций.Async
и ждать по сравнению с*
а такжеyield
более семантический.async
Возвращаемое значение функции — это объект Promise, который более удобен, чем объект Iterator, возвращаемый функцией Generator, и может использоваться напрямую.then()
способ вызова.
Затем давайте проиллюстрируем использование функции async/await с помощью небольшого фрагмента кода:
Функции синхронизации без async/await:
fn = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 2000)
})
}
const Fn = () =>{
fn().then((res) => {
console.log(res)
})
}
Fn()
console.log(2)
Я считаю, что все программисты, которые могут видеть здесь, должны знать выходной статус этого кода: сначала напечатать 2, а затем напечатать 1 через 2 с.
Функции синхронизации с использованием async/await:
fn = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 2000)
})
}
const Fn = async () => {
await fn().then((res) => {
console.log(res)
})
console.log(2)
}
Fn()
Вывод этой функции: 1 печатается через 2 с, а затем печатается 2.
Тогда почему?
Мы понимаем два слова асинхронный и ожидающий буквально: асинхронный означает асинхронный, асинхронный используется для определения асинхронной функции, которая возвращает промис. ; await означает ждать, Promise — это обещание, await — это тоже обещание. Обещание Promise состоит в том, чтобы выводить возвращаемое значение в функцию возврата then, независимо от того, успешно это происходит или нет. Обещание ожидания заключается в том, что независимо от того, ветрено или дождливо, я буду ждать, пока вы закончите выполнять другие шаги. Поэтому в приведенном выше коде, который использует async/await, он будет ждать, пока fn полностью запустится, а асинхронный обратный вызов завершит обработку возвращаемого значения, прежде чем начинать следующую операцию. Идея состоит в том, чтобы превратить асинхронную функцию в синхронную операцию.
практическое использование
В работе на прошлой неделе я много раз использовал async/await в работе сканера, основанной на узле, для управления потоком выполнения программы:
//伪代码
let axiosArr = [];
for (let i = 0, len = arr.length; i < len; i++) {
let params = qs.stringify({
'param': arr[i].index,
})
axiosArr.push(axios.post(url, params, {
headers
}))
}
/*
*上面的循环是循环抓取2345条数据,平均每个数据要访问16个接口
*用axios.all同时询问,当返回结束后将返回值处理
*然后将返回值存储到mongodb数据库中
*/
await axios.all(axiosArr).then(
axios.spread(function () {
for (let i = 0, len = arguments.length; i < len; i++) {
let str = `${unescape(arguments[i].data.replace(/\\u/g, '%u'))}`;
str = basics.subStr(basics.deletN(basics.deletS(basics.cutStr(str))));
concentArr[i].concent = str
}
mg.mongodbMain({
name: obj.name,
alias: obj.alias,
type: type,
url: obj.url,
drugsConcent: concentArr
})
}))
На самом деле операция настолько проста, что все поймут, посмотрев на код. Но проблема в том, что когда я не использую async/await, он сначала получит доступ к 2000+ данным и будет постоянно обращаться к своим 16 интерфейсам, но поскольку функция обратного вызова promise является асинхронной, она будет зависать, и вместо прямого хранения данных в базу данных. Кажется, это отличается от того, что мы ожидали. Поэтому здесь я использую функцию async/await, использую синхронизацию для обработки асинхронных операций и синхронизирую промисы.Когда axios.all обращается к 16 интерфейсам каждого фрагмента данных, данные напрямую сохраняются в базе данных, а затем происходит переход к следующий уровень цикла, есть еще 16 интерфейсов для доступа к следующему фрагменту данных.
Последствия async/await
мы сказалиasync
Возвращаемое значение функции является объектом Promise.
const delay = timeout => new Promise(resolve=> setTimeout(resolve, timeout));
async function f(){
await delay(1000);
await delay(2000);
await delay(3000);
return 'done';
}
f().then(v => console.log(v));// 6s之后打印'done'
Как только внутри он выбрасывает исключение, это приведет к тому, что состояние возврата объекта станет Promisereject
условие. Выданная ошибка будетcatch
Получена функция обратного вызова метода.
async function e(){
throw new Error('error');
}
e().then(v => console.log(v))
.catch( e => console.log(e));//抛出的错误会被catch捕捉到
Кроме того, у async есть схожая с promise.all фича, то есть во внутренней точке есть функция await для сообщения об ошибке, и последующее выполнение выполняться не будет.
let fn1 = ()=>{
return new Promise((resolve,reject) => {
setTimeout(()=>{
reject('故意抛出错误');
},500);
});
}
let fn2 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1);
},500);
});
}
let getList = async ()=>{
let a = await fn1();
let b = await fn2();
return {first: a,second:b};
}
getList().then(result=> {
console.log(result);
}).catch(err=> {
console.log(err);// 由于fn1的报错,async的状态直接变成了rejected
});
Когда появились Promises, казалось, что ад обратных вызовов пришел в упадок. Когда появился Async/Await, асинхронность, наконец, не была сложной вещью.