One Last You Jen Bird
  1. 1 One Last You Jen Bird
  2. 2 Last Surprise Lyn
  3. 3 Life Will Change Lyn
  4. 4 かかってこいよ NakamuraEmi
  5. 5 Time Bomb Veela
  6. 6 Libertus Chen-U
  7. 7 Warcry mpi
  8. 8 Flower Of Life 发热巫女
  9. 9 Hypocrite Nush
  10. 10 BREAK IN TO BREAK OUT Lyn
2017-11-15 12:25:47

更优越的异步解决方案——async await

异步操作是JS的永不过时的话题,总是有人提出各种各样的方案去解决它,最初的回调地狱,到Promise,再有generator函数,直到现在的async函数。


基本规则

声明

定义一个async函数和普通函数的方式无异,可以通过函数声明或者函数表达式,使用如下:

// 函数声明
async function name () {
    ...
}
// 函数表达式
let example = async function() {
    ...
}

特性

那么async函数和普通函数的区别在哪呢?使用上的关键有两点:

  1. 调用该函数后会返回一个Promise对象,当该函数内return一个值时,Promise对象的resolve方法将处理这个值。当函数内抛出异常时,reject方法将处理异常。这部分的值传递方式和Promise链的规则相同。
  2. async函数内可能会有await表达式,await将会等待一个Promise对象。这会使函数暂停执行直到Promise被决议。如果resolve则不必写then直接得到Promise决议值,reject则抛出异常。如果await等待的不是Promise则等同于同步操作。

原理

总的概括,async函数其实没有新的东西,就是基于以前说过的generator函数,自动执行器和Promise的语法糖。

首先将async函数转化为普通的generator函数,其内部的await和yield在语法上完全相同。

async function example (a, b) {
    ....await...
}
// 转化后
function example (a, b) {
    return spawn(function* () {
         ....yield...
    }, this);
}

这个转化由spawn函数实现,这个spawn函数就是一个返回Promise的自动执行器了。

function spawn (genF, self) {
  return new Promise(function (resolve, reject) {
    var gen = genF.call(self);
    step(() => gen.next(undefined));
    function step (nextF) {
      var next;
      try {
        next = nextF();
      } catch(e) {
        // finished with failure, reject the promise
        reject(e);
        return;
      }
      if (next.done) {
        // finished with success, resolve the promise
        resolve(next.value);
        return;
      }
      // not finished, chain off the yielded promise and `step` again
      Promise.resolve(next.value).then(
        v => step(() => gen.next(v)),
        e => step(() => gen.throw(e))
      );
    }
  });
}

-- EOF --

添加在分类「 前端开发 」下,并被添加 「JavaScript」 标签。