1. Promise
异步函数,即async / await ,是基于Promise 的应用,可以让我们以同步的方式写异步的代码。
如下代码,一个使用Promise 的简单例子,Promise 对象中的函数参数中,写了一个定时器setTimeout 。定时器的第三个参数为10 ,表示定时器结束后,10 将作为参数,传递给定时器的回调函数resolve 。这就意味着,定时器结束后,这个Promise 对象会解决为数值10 。
const p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 10));
但是,如果访问到这个数值10 ,需要调用then() 方法:
p.then(x => console.log(x));
这非常不方便,虽然解决了回调地域问题,但是后续代码必须要放在then() 方法里面。
在 ES8 中,JavaScript 支持了async / await 关键字,可以用同步的方式,写异步代码。
2. async 关键字
async 关键字用来声明异步函数,可以在函数声明、函数表达式、箭头函数、方法前声明使用:
async function fun1() {}
const fun2 = async function () {};
const fun3 = async () => {};
const obj = {
async fun4() {},
};
使用async 关键字可以让函数具有异步的特征,但代码还是同步求值的:
async function fun() {
console.log(1);
}
fun();
console.log(2);
如上代码,fun 函数被声明成异步函数,但总体代码仍然是同步执行的,因为先打印出了1 ,再打印2 。
另外,被async 声明的函数如果使用return 返回了值(若没有return ,则返回undefined ),那么返回的值会被Promise.resolve() 包装成一个Promise 对象。所以,异步函数始终会返回Promise 对象。
如下代码,调用fun 函数,fun 函数内部首先打印出1 ,接着返回Promise 对象,然后打印出2 ,最后打印出Promise 对象解决的值3 。
async function fun() {
console.log(1);
return 3;
}
fun().then(console.log);
console.log(2);
异步函数内部直接返回一个Promise 对象也能达到同样效果,如下代码等价于上面的代码:
async function fun() {
console.log(1);
return Promise.resolve(3);
}
fun().then(console.log);
console.log(2);
但是,若Promise 被拒绝,那么将不会被异步函数捕获:
async function fun() {
console.log(1);
Promise.reject(3);
}
fun().then(console.log);
console.log(2);
3. await 关键字
使用await 关键字可以暂停异步函数代码的执行,等待Promise 解决。
本文收个例子:
const p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 10));
p.then(x => console.log(x));
可以使用async 和await 关键字改写为:
async function fun() {
const p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 10));
console.log(await p);
}
fun();
await 关键字会暂停执行异步函数后面的代码,让出 JavaScript 运行时的执行线程。
但是,await 必须和async 一起使用,也就是说,await 只能写在被async 声明过的异步函数中。若await 写在同步函数中,将会报错:
function fun() {
let a = await 1;
console.log(a);
}
fun();
参考:
《JavaScript高级程序设计(第4版)》
📘📘欢迎在我的博客上访问: https://lzxjack.top/
|