es6的async函数学习

async函数的使用方式,直接在普通函数前面加上async,表示这是一个异步函数,在要异步执行的语句前面加上await,表示后面的表达式需要等待。async是Generator的语法糖,相比较Generator函数在以下四方面做了改进

async相对于Generator的优点

1.有内置执行器,不用调用next

Generator函数是需要调用next指令来运行异步的语句,async不需要调用next,直接像运行正常的函数那样运行就可以

2.有更好的语义化

语义化更明确,相比较于Generator的*和yield,async和await更明确。

3.await后面可以跟promise或者任意类型的值

yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。

4.返回一个promise对象,可以调用.then

async直接返回一个promise对象,可以用then和cache来处理。

    async function getStockPriceByName(name) {
        let symbol = await getStockSymbol(name);
        let price = await getPriceByName(symbol);
        return price
    }
    getStockPriceByName('goog').then( (result)=> {
        console.log(result);
    }).catch((err)=>{
         console.log(err)
    })

上面的async异步函数遇到await会先返回一个Promise对象,等到异步操作执行完毕,才会根据结果来执行具体的回调函数。

async 函数多种形式

  1. 函数声明

     async function foo() {}
  2. 表达式声明

    var bar = async function () {}
    
  1. 对象声明

        var obj = {
            async bazfunction(){
            }
        }
  2. 箭头函数声明

       var fot = async() => {  }

await 语句

  1. await后面是一个promise对象,如果不是,会转成一个resolve的promise对象

      async function f() {
          return await 123;
      }
      f().then(function (a) {
          console.log(a);
      })
  1. await后面的promise对象,如果reject,则reject参数会被cache参数接收到,写不写return都可以,并且reject下面的代码不会执行,如果想下面的代码执行,必须用try cache包住

      async function a() {
           try{
              await Promise.reject('出错了!')
           }catch (e){
              return await Promise.resolve('请重新填写') 
           }
      }
      a().then(function () {
         console.log(err);
      }).catch(function (err) {
          console.log(err);
      })

上面的代码如果不用try cache包裹reject,则下面的代码不会执行,并且reject语句是不用return返回的,resolve语句是需要用return返回;

async错误处理常用写法

如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。所以通常的处理方法有两种

  1. 用try catch包住可能会出错的部分

      async function myFunction() {
          try {
              await somethingThatReturnsAPromise();
          } catch (err) {
              console.log(err);
          }
      }
  1. 另一种写法是对可能要出错的异步操作添加catch回调函数

   async function myFunction() {
           await somethingThatReturnsAPromise().catch((err)=> {
                   console.log(err);
           })
       }

多个await语句同时触发

  let a=await getFoo();
  let b=await getBar();

上面的两个方法都是异步操作,不存在依赖关系,所以我们可以同时触发,改写成下面的

  //第一种写法
  let [a,b]=Promise.all([getFoo(),getBar()])
  //第二种写法
  let aPromise=getFoo();
  let bPromise=getBar();
  let a=await aPromise;
  let b=await bPromise;

async 函数的实现原理

async函数就是将执行器和Generator做为一个函数返回。

  async function fn(){}
  //等同于
  function fn() {
    return spawn(function* () {
      
    })
  }
  function spawn(genF) {
          /****
           * 返回的是一个promise
           */
          return new Promise(function(resolve, reject) {
              var gen=genF(); //运行Generator这个方法;
              /***
               * 执行下一步的方法
               * @param fn 一个调用Generator方法的next方法
               */
             function step(fn) {
                  //如果有错误,则直接返回,不执行下面的await
                 try {
                  var next=fn();
                 }catch (e){
                   return reject(e)
                 }
                  //如果下面没有yield语句,即Generator的done是true
                 if(next.done){
                    return resolve(next.value);
                 }
                 // 如果下面还有yield语句,resolve继续执行递归执行gen.next(),reject则抛出错误
                 Promise.resolve(next.value).then((val)=>{
                     step(function(){ return gen.next(val) } )
                 }).catch((e)=>{
                     step(function(){ return gen.throw(e) } )
                 })
             }
              step(function () {
                 return gen.next();
             })
          });
      }

参考阮大神的文章:http://es6.ruanyifeng.com/#do...

你可能感兴趣的:(es6的async函数学习)