简单介绍
异步函数是ES8新增的,用来解决利用异步结构组织代码的问题,是javaScript最重要的工具之一。
它有两个关键字:async、await。
async关键字用来声明函数为异步函数,使函数有异步特性。
异步函数的特性
1、如果有返回值n,会返回一个被Promise.resolve(n)包装的Promise对象。
async function foo(){
return 1
}
foo().then(console.log)//1
//效果等同于
async function foo() {
return Promise.resolve(1)
}
foo().then(console.log)//1
2、能捕获抛出的错误,但不能捕获拒绝状态的Promise,这跟Promise捕获机制相反了
async function foo1(){
throw 1
}
foo1().catch(console.log)//1
async function foo2() {
Promise.reject(3)
}
foo2().catch(console.log) //不能捕获,无打印
/* 最终打印错误未被捕获的报错信息*/
3、async不能声明箭头函数
async/await
await关键字可以暂停异步函数代码的执行,等待Promise解决,再往后执行。
//async函数不使用await关键字,和普通函数基本没区别
async function foo() {
let p = new Promise((resolve) => setTimeout(resolve,1000,1))
console.log(p);
console.log(2);
}
//使用await关键字,就有了等待的效果
foo()//先打印Promise { <pending> } ,再打印2
async function foo() {
let p = new Promise((resolve) => setTimeout(resolve,1000,1))
console.log(await p);
console.log(2);
}
foo()//先打印1 ,再打印2
await关键字只能出现在异步函数的顶层主体,否则会抛出SyntaxError错误:SyntaxError: await is only valid in async functions and the top level bodies of modules
async function foo() {
let p = new Promise((resolve) => setTimeout(resolve,1000,1))
console.log(await '1');//1
setTimeout(() => { await '1' }, 500)//报错:await is only valid in async functions and the top level bodies of modules
}
注意:await并非只是等待一个值,那么简单。javaScript 运行的时候,遇到await 关键字会记录它暂停的位置,也就是添加到了任务队列中,等到右边的值可用了,javaScript会向消息队列中推送一个恢复异步函数执行的任务。即使await的是一个直接可用的值也是一样的。
异步函数策略
异步函数策略只是一些应用场景
1、实现异步延迟
async function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay))
}
async function foo() {
const startTime = Date.now()
await sleep(1500);//延迟约500ms
console.log(`耗时:${Date.now() - startTime}ms`);
}
foo()
2、平行执行
async function randomDelay(id) {
const delay = Math.random() * 1000;
return new Promise((resolve) => setTimeout(() => {
// console.log(`${id} finished`);
setTimeout(console.log, 0, `${id} finished`)
resolve();
}), delay)
}
async function foo() {
const start = Date.now()
const p0 = randomDelay(0);
const p1 = randomDelay(1);
const p2 = randomDelay(2);
const p3 = randomDelay(3);
const p4 = randomDelay(4);
await p0;
await p1;
await p2;
await p3;
await p4;
// console.log(`耗时:${Date.now() - start} ms`);
setTimeout(console.log, 0, `耗时:${Date.now() - start} ms` )
}
foo()
/* 输出打印:
0 finished
1 finished
2 finished
3 finished
4 finished
耗时:14 ms
*/
3、串行执行
async function add1(x) { return x + 1}
async function add2(x) { return x + 2 }
async function add3(x) { return x + 3 }
async function adds(value) {
let result = value
for (const fn of [add1, add2, add3]) {
result = await fn(result);
}
return result
}
adds(9).then(console.log) //15