ES6之异步流程的前世今生(下)

generator/co

讲之前先来看一个es6的东西

  function* foo() {
      yield 1;
      yield 2;
      yield 3;
      return console.log(4)
  }

  var it = foo();
  it.next();
  it.next();
  it.next();
  it.next(); //4
function *doSomething() {

    console.log(‘start’)
    yield
    console.log(‘finish’)

}
var func1 = doSomething();
func1.next();
func1.next();

function* getStorckPrice(stock) {

    while (true) {
        yield Math.random() * 100;
    }

}
var priceGenerator = getStockPrice(‘IBM’);
var limitPrice = 15;
var price = 100;
while (price > limitPrice) {
    price = priceGenerator.next().value;
    console.log( `this generator return ${price}` );
}
console.log( `buying at ${price}` );

generator 原理

我们 Google 了一下,这个是 facebook 下的一个工具:regeneratorRuntime ,用于编译 ES6 的 generator 函数。

我们进行下载

然后创建一个generator, js文件

执行以下代码

以下称为编译简单版, 这个肯定是不能跑的,因为有我们遇到的 regeneratorRuntime。wap.

主要用到迭代器的 Iterator.next 的调用。

regenerator --include-runtime geberator.js > generator-es5.js

或者可以得出一个编译后 700 多行的点东西,我们抽离除主要逻辑

还有

接下来我们看一下 mark 函数

里面 GeneratorFunctionPrototype 和 Gp 变量, 我们查看对应的代码:

function Generator(){}

function GeneratorFunction(){}

ES6

它们的作用就是维持关系链,跟原生的保持一致。例如:

我们将 next、throw、return 函数怪哉gp对象上。

所以当我们 hell = hllGenerator() 的时候,执行的其实是 wrap 函数,wrap 函数返回一个 generator, generator 对象,她有 outerFn、outerFn. 其实就是genFun.prototype, getFun.prototype 是一个控对象,原型上面有next()方法。hell.next() 的时候,其实是 generator._invoke = makeInvokeMethod(innerFn, self, context); 这里的 innerFun 就是wrap 包裹的函数。hiGenerator接下来我们看一下 makeInvokeMethod 函数里面的主要功能是 invoke 函数 根据不同的context状态来进行相应的操作。hi.next()=>record=> innerFn.call(self, context)=>abrupt,我们 record 对象。这个对象有 complete 方法。


语法上generator,有两个特征:

  • function 关键字与函数名之前有一个星号.

  • 函数体内部使用yield关键字,定义不同的内部状态。

    generator 本意是 iterator 生成器,函数运行到yield时退出,并保留上下文。控制函数的执行过程,手工暂停和恢复代码执行. generator 的弊端是没有执行器,本身也不是为流程控制而生的,所以出现了co co 是 tj 大神开发的库 github地址

async/await

async 函数的执行过程

1)await帮我们处理了 promise,要么返回兑现的值,要么抛出异常;

2)await在等待 promise 兑现的同时,整个 async 函数会挂起,promise 兑现后再重新执行接下来的代码。

async/await 原理

我们用 babel 编译下,async/await转换出什么。

yeah,瞬间好长一串,不过莫慌。我们先理性(慌张)分析一波。 它先定义了 三个个函数 asyncGeneratorStep、 _asyncToGenerator、tell wow, 我们发现就tell这个函数我们看的懂,而且很熟悉, Promsie(不熟悉的先去补补上面的知识),ok, 在看剩下来的两个函数。我们大概分析下,asyncGeneratorStep 这个应该是根据不同的状态我们要怎么处理(做具体的事情)。 _asyncToGenerator、tell 这个函数呢,则是将传入的函数变量做分配处理,起分配作用。(不做具体事情)。

接来下我们看看 a定义的这个主函数。整个采用了switch模式,根据不同的状态,分发事件。

根据以上原理 我们可以写一个简易版的

generator()生成它的控制器。接着调用 handle 函数,并传入 interator.next(), 接着遇到 yield 生成器再次挂起,把结果(promsie)传给 handle,接着在执行 interatorValue.then(),将异步请求的值传给 interator.next(), 再次执行生成器。最后当(iteratorResult.done)为true时,退出。

await 的用法 大概分为三种:

  • await + async

  • await + Promise

  • await + co + generaor

后记

相关知识参考资料

Promises/A+规范-英文

Promises/A+规范-翻译1

Promises/A+规范-翻译-推荐

JS执行栈

Javascript异步编程的4种方法

最后更新于

这有帮助吗?