async/await

公司的前端工程使用了ES6语法,最近看代码的时候还是有很多疑惑的,记录一下async/await相关知识

1. async function

使用谷歌浏览器开发者工具写脚本进行测试

  • 按F12打开开发者工具
  • 点击Source
  • 在左侧选择Snippets,点击New snippets创建一个新文件
    async/await
  • 输入以下代码
async function add(x) {
    let a = 1;
    return x + a;
}
add(10);
  • 运行此脚本,在控制台可以看到有结果输出
    async/await
  • 返回的结果是一个Promise对象,状态是fulfilled,值是11
    async/await

2. await语法

  • await 放置在Promise调用之前,强制后面的代码等待,直到Promise对象resolve,得到resolve的值作为await表达式的运算结果
  • await只能在async函数内部使用,用在普通函数里会报错

新建一个脚本文件,输入以下代码:

function test_promise() {
    return new Promise(function(resolve, reject) {
        resolve('resolve result')
    });
}

async function run_test() {
    let a = await test_promise()
    let b = await ' and a simple string'
    console.log(a)
    console.log(b)
    return a + b
}

run_test();

运行结果为:
async/await


给test_promise方法添加延时,修改test_promise()方法

function test_promise() {
    return new Promise(function(resolve, reject) {
        setTimeout(() => {
            resolve('resolve result')    
        }, 3000)
    });
}

运行结果为:
async/await
注意,PromiseResult的值即为run_test()方法的返回值

3. 错误处理

3.1

function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {reject('error')}, ms);
    });
}

async function asyncPrint(ms) {
    console.log('start');
    await timeout(ms);  //这里返回了错误
    console.log('end'); //所以这句代码不会被执行了
}

asyncPrint(1000);

运行结果:
async/await
本例中我们并没有捕获错误,控制台打印 Uncaught error

3.2 捕获错误

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {reject('error')}, ms);  //reject模拟出错,返回error
  });
}

// 使用 try catch 捕获异常,包括promise对象reject的数据或者抛出的异常
async function asyncPrint(ms) {
  try {
     console.log('start');
     await timeout(ms);
     console.log('end');
  } catch(err) {
     console.log(err);
  }
}

asyncPrint(1000);

或者使用如下方式捕获异常

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {reject('error')}, ms);  //reject模拟出错,返回error
  });
}
async function asyncPrint(ms) {
  console.log('start');
  await timeout(ms)
  console.log('end'); 
}
asyncPrint(1000).catch(err => {
    console.log(err)
});

运行结果:
首先打印了start,然后在执行timeout函数时,调用reject回调。错误被捕获,打印出"error"。
async/await
如果想在出现异常后仍然执行后续代码,示例代码如下:

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('error')
    }, ms);
  });
}
async function asyncPrint(ms) {
  console.log('start');
  await timeout(ms).catch(err => {
        console.log(err) 
  })
  console.log('end');
}

asyncPrint(1000);

运行结果:
async/await

4. Promise.all()

多个await命令的异步操作,如果不存在依赖关系(后面的await不依赖前一个await返回的结果),用Promise.all()让它们同时触发

function test1 () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1)
        }, 1000)
    })
}

function test2 () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2)
        }, 2000)
    })
}

async function exc1 () {
    console.log('exc1 start:',Date.now())
    let res1 = await test1();
    let res2 = await test2();
    console.log('exc1 end:', Date.now())
}

async function exc2 () {
    console.log('exc2 start:',Date.now())
    let [res1, res2] = await Promise.all([test1(), test2()])
    console.log('exc2 end:', Date.now())
}

exc1();
exc2();

运行上述代码可得,执行exc1函数耗时约为3秒,而执行exc2函数耗时约为2秒。表明在exc2函数中, 使用Promise.all同时触发了test1和test2这2个异步函数。

上一篇:拉勾大前端高薪训练营013期 网盘分享


下一篇:async | await