async/await—异步编程方式

async 和 await

1.async await含义

async是Generator函数的语法糖

generator: generator返回一个迭代器,每次使用迭代器的next方法执行,每次执行都是执行到下一次的yield

const fs = require('fs');

const readFile = function (fileName) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
      if (error) return reject(error);
      resolve(data);
    });
  });
};

const gen = function* () {
	// yield表达式就是暂停标志
	// yield类似于return,但yield是返回本次 de 函数执行的返回值
	const f1 = yield readFile('/etc/fstab');
	const f2 = yield readFile('/etc/shells');
	console.log(f1.toString());
	console.log(f2.toString());
};

执行generator

let genIterator = gen();
genIterator.next();  //{value: , done: }
genIterator.next();

将上面的gen函数写成async函数

const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');
  const f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

async和gen函数之间的区别

  1. async函数就是将Generator函数的星号(*)替换成async,将yield替换成await
  2. async内置执行器,async函数的执行与普通函数一模一样,只要一行。而gen函数的执行必须依靠执行器,需要调用next方法才能执行
  3. async有更好的语义。async表示函数里有异步操作,await表示紧跟在后面的代码需要等待结果
  4. async函数的返回值是Promise对象gen函数的返回值是Iterator对象。所以async函数可以使用.then进行回调

2.async基本用法

async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成后,再接着执行函数体内后面的语句

  • async函数返回一个Promise对象

  • async函数内部return语句返回的值,会成为then方法回调函数的参数

    async function f() {
      return 'hello world';
    }
    
    f().then(v => console.log(v))
    // "hello world"
    
  • async函数内部抛出错误,会导致返回的Promise对象变为reject状态,并且会被catch方法接收

    async function f() {
        throw new Error('出错了');
    }
    f().then().catch((e)=>console.log(e))  //出错了
    
  • Promise对象的状态变化

    1. 当遇到return或抛出错误,则从async函数体中跳出,并且如果是抛出错误的跳出则Promise为rejected状态
    2. 只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数
  • await命令后面是一个Promise对象/thenable对象,返回该对象的结果,如果不是Promise对象,就直接返回对应的值

    如果await命令后的Promise对象如果变成reject状态,则整个async函数都会中断执行,并且reject的参数会被catch方法的回调函数接收

    解决办法:

    //方法1
    async function f() {
      //try catch块捕获异常
      try {
        //可写多个await命令
        await Promise.reject('出错了');
      } catch(e) {
        
      }
        //这样不管上述异步操作是否成功,第二个await都会执行并return
        return await Promise.resolve('hello world');
    }
    
    f()
    .then(v => console.log(v))
    // hello world
    
    //方法2
    async function f() {
    await Promise.reject('出错了')
      .catch(e => console.log(e));// 出错了
    return await Promise.resolve('hello world');
    }
    
    f()
    .then(v => console.log(v))
    // hello world
    

3.使用注意点

  1. await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try…catch代码块中,否则会导致跳出代码块

  2. 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发

    let foo = await getFoo(); //getFoo执行完才能执行getBar
    let bar = await getBar();
    

    上面代码中,getFoo和getBar是两个独立的异步操作,只有getFoo完成以后,才会执行getBar

    写成同时触发的方式

    // 写法一
    let [foo, bar] = await Promise.all([getFoo(), getBar()]);
    
    // 写法二
    let fooPromise = getFoo();
    let barPromise = getBar();
    let foo = await fooPromise;
    let bar = await barPromise;
    
  3. await命令只能用在async函数之中,如果用在普通函数,就会报错

  4. async 函数可以保留运行堆栈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值