1、async / await
前面添加了async的函数在执行后都会自动返回一个Promise对象
function fn() {
return 'leo';
}
console.log(fn()); // 'leo'
添加async后
async function fn() {
return 'leo'; // Promise.resolve('leo')
}
console.log(fn()); // Promise对象
async函数中使用await,那么await处的代码就会变成同步的,即只有等await后面的Promise执行完成得到结果才会继续往下执行,await意为等待
function timeout() {
return new Promise(resolve => {
setTimeout(() => {
console.log(1);
resolve();
}, 1000);
})
}
async function fn() {
await timeout(); // 执行完成才继续往下执行
console.log(2);
}
fn(); // 不加async和await是 2、1,加了是 1、2
注意:
1、await 只能在 async 标记的函数内部使用,单独使用会触发 Syntax error;
2、await后面需要跟异步操作,不然就没有意义,而且await后面的Promise对象不必写then,因为await的作用之一就是获取后面Promise对象成功状态传递出来的参数。
2、Promise.prototype.finally()
Promise执行时,无论结果是fulfilled或者是rejected,在执行then()或catch()后,都会执行finally()指定的回调函数,可以避免同样的语句需要在then()和catch()中各写一次的情况
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 1000);
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
}).finally(() => { // 无论Promise结果是then(),即resolve;还是catch(),即reject,最后都会执行finally()
console.log('finally');
})
如每次请求发送完毕,就需要关闭loading提示框,不管请求成功或是失败,这个loading都需要关闭掉,这时把关闭loading的代码写在finally里再合适不过了。
3、Promise.allSettled()
已知Promise.all() 具有并发执行异步任务的能力。但它的最大问题就是如果其中某个任务出现异常(reject),所有任务都会挂掉,且直接进入reject 状态。
如页面上有三个请求,分别请求不同的数据,如果使用Promise.all(),一个接口服务异常,整个都是失败的,都无法渲染出数据。
我们想要在并发任务中,无论一个任务正常或者异常,都会返回对应的的状态,则可以使用
let promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise1");
}, 3000);
});
};
let promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise2");
}, 1000);
});
};
let promise3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("error promise3");
}, 2000);
});
};
// 使用Promise.all,则会走到catch里面,因为promise3是reject
Promise.all([promise1(), promise2(), promise3()])
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log("error", error); // error promise3
});
// 使用Promise.allSettled,不管有没有错误,三个状态都会返回,不会走到catch
Promise.allSettled([promise1(), promise2(), promise3()])
.then((res) => {
console.log(res);
// [
// {status: 'fulfilled', value: 'promise1'},
// {status: 'fulfilled', value: 'promise2'},
// {status: 'rejected', reason: 'error promise3'}
// ]
})
.catch((error) => {
console.log("error", error);
});
4、Promise.any() 和 AggregateError
Promise.any 与 Promise.all() 正好相反。如果任何承诺得到解决, Promise.any() 将被触发。
另一方面, Promise.all() 将等到所有承诺都得到解决。以下是 any()、all() 和 allSettled() 的区别。
any() — 如果至少有一个承诺被解决,这将执行,如果所有承诺都被拒绝,则将拒绝。即哪个resolve快就执行哪个。
all() — 如果所有承诺都得到解决,这将执行,如果至少一个承诺被拒绝,则将拒绝。
allSettled() — 如果所有承诺都已解决或被拒绝,这将执行。
// 创建一个Promise
const promise1 = new Promise((resolve, reject) => {
// 2秒后resolve()
setTimeout(() => resolve("The first promise has been resolved."), 2000);
});
// 创建一个Promise
const promise2 = new Promise((resolve, reject) => {
// 1秒后resolve()
setTimeout(() => resolve("The second promise has been resolved."), 1000);
});
// 创建一个Promise
const promise3 = new Promise((resolve, reject) => {
// 3秒后resolve()
setTimeout(() => resolve("The third promise has been resolved."), 3000);
});
(async function () {
const data = await Promise.any([promise1, promise2, promise3]);
// promise2最短时间resolve()
console.log(data); // The second promise has been resolved.
})();
如果所有 Promise 都被拒绝,则会抛出 AggregateError 异常。
// 创建一个Promise
const promise1 = new Promise((resolve, reject) => {
// 1s后reject()
setTimeout(() => reject("The first promise has been rejected."), 1000);
});
// 创建一个Promise
const promise2 = new Promise((resolve, reject) => {
// 0.5s后reject()
setTimeout(() => reject("The second promise has been rejected."), 500);
});
// 处理异常
(async function () {
try {
const data = await Promise.any([promise1, promise2]);
console.log(data);
} catch (error) {
// 如果所有的Promise都是reject()
// 捕获aggregate errors.
console.log("Error: ", error);
}
})();