async/await 是语法糖,异步的本质还是回调函数
async/await 语法
- 异步回调容易产生 callback hell(回调地狱)
- Promise then catch 链式调用,但也是基于回调函数
- async/await 是同步语法,彻底消灭回调函数,代码演示:
js
//加载图片
function loadImg(src) {
const p = new Promise((resolve, reject) => {
const img = document.createElement('img');
img.onload = () => {
resolve(img);
};
img.onerror = () => {
const err = new Error(`图片加载失败 ${src}`);
reject();
};
img.src = src;
});
return p;
}
const src1 =
'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png';
const src2 =
'https://box.bdimg.com/static/fisp_static/common/img/searchbox/logo_news_276_88_1f9876a.png';
// !用于解决报错 Uncaught TypeError: "https..." is not a function is not a function
!(async function () {
// 同步的写法
const img1 = await loadImg1(); //也可以直接用 loadImg(src1)
console.log(img1.width, img1.height);
const img2 = await loadImg2(); //也可以直接用 loadImg(src2)
console.log(img2.width, img2.height);
})();
async function loadImg1() {
const img1 = await loadImg(src1);
return img1;
}
async function loadImg2() {
const img2 = await loadImg(src2);
return img2;
}
async/await 和 Promise 的关系
- async/await 是消灭异步回调的终极武器
- 但和 Promise 并不互斥,反而两者相辅相成
- 执行 async 函数,返回的是 Promise 对象
js
async function fn1() {
return 100;
// return Promise.resolve(200)
}
const res1 = fn1(); // 执行 async 函数,返回 Promise 对象
console.log('res1', res1); // res1 Promise
res1.then((data) => {
console.log('data1', data); // data1 100
});
- await 相当于 Promise 的 then
js
async function fn1() {
return 100;
// return Promise.resolve(200)
}
!(async function () {
const p1 = Promise.resolve(300);
const data = await p1; // await 相当于 Promise then
console.log('data', data); // data 300
})();
!(async function () {
const data1 = await 400; // 直接返回 400
console.log('data', data1); // data 400
})();
!(async function () {
const data2 = await fn1(); // await 相当于 Promise.resolve(100)
console.log('data', data2); // data 100
})();
- try...catch 可捕获异常,代替了 Promise 的 catch
js
!(async function () {
const p4 = Promise.reject('err'); // rejected状态
try {
const res4 = await p4;
console.log('res4', res4); // 不执行
} catch (e) {
console.error('err4', e); //err4 err try…catch 相当于 Promise catch
}
})();
// 没有 try…catch 无法捕获错误
!(async function () {
const p5 = Promise.reject('err1'); // rejected状态
const res5 = await p5; // await -> then,下面不会执行
console.log('res5', res5); // 不执行
})();
异步的本质
- async/await 是消灭异步回调的终极武器
- JS 还是单线程,还得是有异步,还得是基于 event loop
- async/await 只是一个语法糖,代码演示:
js
async function async1() {
console.log('async1 start'); // step 2
await async2(); //undefined
// await 的后面,都可以看做是 callback 里的内容,即异步
// 类似 event loop,setTimeout(function(){ console.log('async1 end')})
// 或 Promise.resolve().then(()=>{console.log('async1 end')})
console.log('async1 end'); // step 5
}
async function async2() {
console.log('async2'); // step 3
}
console.log('script start'); // step 1
async1();
console.log('script end'); // step 4
// 同步代码已经执行完(event loop)
// script start
// async1 start
// async2
// script end
// async1 end
再看一个例子:
js
async function async1() {
console.log('async1 start'); // step 2
await async2();
// 下面都是异步回调 callback 的内容
console.log('async1 end'); // step 5
await async3();
// 下面都是异步回调 callback 的内容
console.log('async1 end 2'); // step 7
}
async function async2() {
console.log('async2'); // step 3
}
async function async3() {
console.log('async3'); // step 6
}
console.log('script start'); // step 1
async1();
console.log('script end'); // step 4
// 同步代码已经执行完(event loop)
// script start
// async1 start
// async2
// script end
// async1 end
// async3
// async1 end 2
补充 for ... of 异步的使用
- for ... in (以及 forEach for )是常规的同步遍历
- for ... of 常用于异步的遍历
js
function muti(num) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(num * num);
}, 1000);
});
}
const nums = [1, 2, 3];
nums.forEach(async (i) => {
// 1秒后同步执行
const res = await muti(i); // 相当于 Promise 的 then
console.log(res); // 1 4 9
});
!(async function () {
for (let i of nums) {
// 1秒执行一个
const res = await muti(i); // 相当于 Promise 的 then
console.log(res); // 1 4 9
}
})();