предисловие
Содержание, включенное в статью, может быть неполным, но его много, и его нужно читать медленно. Мне потребовалось много времени, чтобы организовать и поделиться своим опытом с сердцем, надеясь помочь всем. Но это неизбежно, что будут опечатки или недоразумения.Я надеюсь, что вы можете написать мне по электронной почте ghui_master@163.com, если вы их найдете, и я внесу изменения вовремя.Я просто надеюсь помочь вам, спасибо.
Тукао и хвастовство
Что касается асинхронной обработки, обратные вызовы ES5 отправили нас в ад, обещания ES6 вывели нас из магического барьера, и, наконец, асинхронное ожидание ES7 вывело нас на свет. Узнайте об асинхронном ожидании сегодня. сесть в машину
Связь между асинхронным ожиданием и обещанием
Гуси, побывавшие в крупных технических сообществах, часто видят такие слова. С async-await надо ли учить промисы, а async await превосходит промисы. Увидев такую информацию, гуси тоже в замешательстве. Теперь я знаю, что async-await — это синтаксический сахар для промисов и генераторов. Просто чтобы сделать наш код более плавным и, конечно же, улучшить читаемость кода. Проще говоря: async-await построен на механизме промисов и не может заменить его статус. Вы понимаете? ? ?
все равно начнем с азов
async function func() {
let result = await Math.random();
console.log(result);
}
func();
<!--输出-->
0.8177900460417995
Promise:{<resolved>: undefined}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
Каштан выше — это базовый синтаксис async-await. Есть два незнакомых ключевых слова async и await, и результат выполнения функции, кажется, возвращает объект обещания.
async
Async используется для указания того, что функция является асинхронной.Возвращаемое значение определенной асинхронной функции является объектом обещания, а метод then может использоваться для добавления функции обратного вызова.
async function func1() {
return 123;
}
func1().then(val => {
console.log(val); // 123
});
<!--
若 async 定义的函数有返回值,return 123;
相当于Promise.resolve(123),没有声明式的 return则相当于执行了Promise.resolve();
-->
await
await можно понимать как сокращение для асинхронного ожидания. await должен появляться внутри асинхронной функции и не может использоваться отдельно. Пока в функции используется await, текущая функция должна быть украшена асинхронным
function notAsyncFunc() {
await Math.random();
}
notAsyncFunc();
<!--
Uncaught SyntaxError: Unexpected identifier
Uncaught SyntaxError: await仅在异步函数中有效
-->
За ожиданием может следовать любое выражение JS. Хотя await может ожидать многих типов вещей, его основная цель — дождаться разрешения состояния объекта Promise. Если ожидание является объектом обещания, это приведет к остановке выполнения асинхронной функции и ожиданию разрешения обещания, а если ожидание является обычным выражением, оно будет выполнено немедленно.
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(' enough sleep~');
}, second);
})
}
function normalFunc() {
console.log('normalFunc');
}
async function awaitDemo() {
await normalFunc();
console.log('something, ~~');
let result = await sleep(2000);
console.log(result);// 两秒之后会被打印出来
}
awaitDemo();
<!-- 输出 -->
VM899:9 normalFunc
VM899:13 something, ~~
Promise:{<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
VM889:15 enough sleep~
Я надеюсь взять этот маленький каштан, чтобы помочь всем понять вышеизложенное.
Возьмем реальный пример
В реальной разработке у вас есть три запроса, которые должны произойти, и третий запрос — это деконструкция, которая зависит от второго запроса, второй запрос зависит от результата первого запроса.
Если реализовано с помощью ES5, будет 3 уровня обратных вызовов, а если реализовано с помощью Promise, потребуется как минимум 3 then.
Горизонтальное развитие - код, другой - продольное развитие. Сегодня главный герой - достичь Async-a ждать, ха ~
//我们仍然使用 setTimeout 来模拟异步请求
function sleep(second, param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(param);
}, second);
})
}
async function test() {
let result1 = await sleep(2000, 'req01');
console.log(` ${result1}`);
let result2 = await sleep(1000, 'req02' + result1);
console.log(` ${result2}`);
let result3 = await sleep(500, 'req03' + result2);
console.log(` ${result3}`);
}
test();
<!-- 输出
Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
VM913:14
req01
req02req01
req03req02req01
-->
отклонить обработку
Все вышеперечисленные случаи разрешены, а как насчет обработки отклонения?
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('want to sleep~');
}, second);
})
}
async function errorDemo() {
let result = await sleep(1000);
console.log(result);
}
errorDemo();// VM706:11 Uncaught (in promise) want to sleep~
// 为了处理Promise.reject 的情况我们应该将代码块用 try catch 包裹一下
async function errorDemoSuper() {
try {
let result = await sleep(1000);
console.log(result);
} catch (err) {
console.log(err);
}
}
errorDemoSuper();// want to sleep~
// 有了 try catch 之后我们就能够拿到 Promise.reject 回来的数据了。
Внимание впереди высокая энергия (параллельная обработка)! ! !
У новичков параллельный запрос ajax случайно отправляется в блокировку операции синхронизации, и я действительно писал такой код на работе. await остановится, если дождется обещания. Реальный бизнес такой, у меня есть три асинхронных запроса на отправку, которые не связаны друг с другом, мне просто нужно очистить загрузку интерфейса, когда все запросы закончатся. Только что закончил изучение асинхронного ожидания Happy, используйте его везде~
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request done! ' + Math.random());
}, second);
})
}
async function bugDemo() {
await sleep(1000);
await sleep(1000);
await sleep(1000);
console.log('clear the loading~');
}
bugDemo(); // 等待一会输出 clear the loading~
загрузка действительно очищается после ожидания завершения всех запросов. Но вы внимательно наблюдаете, что запрос временной шкалы браузера отправляется после его завершения (если вы наблюдаете эффект, отправьте настоящий запрос ajax)
Итак, каково нормальное обращение?
async function correctDemo() {
let p1 = sleep(1000);
let p2 = sleep(1000);
let p3 = sleep(1000);
await Promise.all([p1, p2, p3]);
console.log('clear the loading~');
}
correctDemo();// clear the loading~
Well, perfect. See, async await doesn't replace promise
ждать в цикле for
await должно быть в контексте асинхронной функции, ожидание допустимо только в асинхронных функциях.
// 正常 for 循环
async function forDemo() {
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i ++) {
await arr[i];
}
}
forDemo();//正常输出
// 因为想要炫技把 for循环写成下面这样 (然而吧)
async function forBugDemo() {
let arr = [1, 2, 3, 4, 5];
arr.forEach(item => {
await item;
});
}
forBugDemo();// Uncaught SyntaxError: Unexpected identifier
----------------------
async function forBugDemo() {
let arr = [1, 2, 3, 4, 5];
arr.forEach(async (item) => {
await item;
}); // 这样就不会报错了,但是await后面的异步不会等待执行,因为forEach底层是while循环
}
forBugDemo();
hahaha
Новый «синтаксический сахар» в ES7: async await
- Пока в функции используется await, текущая функция должна быть украшена асинхронным
- Асинхронность предназначена для украшения функции, управления ее возвращаемым результатом является экземпляром Promise.
- await можно понимать как изменение асинхронной операции как синхронного эффекта (но это все еще асинхронно)