Generator

本文深入探讨了JavaScript中的协程概念及其实现方式——Generator函数。通过实例解析了协程的工作流程,展示了如何使用yield命令暂停和恢复执行,以及如何在Generator函数中进行数据交换和错误处理。此外,还解释了如何通过.next()方法分段执行Generator函数并传递参数。
摘要由CSDN通过智能技术生成

解决异步的其中一个办法是“协程”;意思是多个线程互相合作,完成异步任务;

function* asyncJob() {
  // ...其他代码
  var f = yield readFile(fileA);
  // ...其他代码
}

一、协程的运行流程大致:

  • 协程A开始执行;
  • 协程A执行到一半,进入暂停,执行权转移到协程B;
  • (一段时间后),协程B交换执行权;
  • 协程A恢复执行。

上面代码的函数asyncJob是一个协程,它的奥妙就在其中的yield命令。它表示执行到此处,执行权将交给其他协程。也就是说,yield命令是异步两个阶段的分界线。

协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。它的最大优点,就是代码的写法非常像同步操作,如果去除yield命令,简直一模一样。

二、协程的Generator函数实现

Generator函数是协程在ES6的实现,最大特点就是可以交出函数的执行权(即暂停执行)。
整个Generator函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。Generator函数的执行方法如下。

function* gen(x) {
    var y = yield x + 2;
    return y;
  }
var g = gen(1);
console.log(g.next()) // { value: 3, done: false }
console.log(g.next()) // { value: undefined, done: true }

function* gen(x) {
    var y = yield x + 2;
    return 2;
  }
声明迭代器  
var g = gen(1);
此时g是一个迭代器的引用
console.log(g.next()) // { value: 3, done: false }
console.log(g.next()) // { value: 2, done: true }

调用Generator函数,会返回一个内部指针(即遍历器)g。这是Generator函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针g的next方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的yield语句,上例是执行到x + 2为止。

换言之,.next方法的作用是分段执行Generator函数;每次调用next方法,会返回一个对象,表示当前阶段的信息(value属性和done属性)。value属性是yield语句后面表达式的值,表示当前阶段的值;done属性是一个布尔值,表示Generator函数是否执行完毕,即是否还有下一个阶段。

function* helloWorldGenerator() {
    yield 'hello';
    yield 'world';
    return 'ending';
}  
// 声明迭代器;每个迭代器之间是相互独立的,作用域独立;
var hw = helloWorldGenerator();
var hwG = helloWorldGenerator();
console.log(hw.next()) // { value: 'hello', done: false }
console.log(hw.next()) // { value: 'world', done: false }
console.log(hw.next()) // { value: 'ending', done: true }
console.log(hwG.next()) // { value: 'hello', done: false }

注意:generator函数中的.next()方法可以接收参数

传入的参数,把上一个yield语句返回的值给覆盖掉;

第一个.next()是启动器,在它之前没有yield语句,所以给第一个.next()传参没有意义;

function* foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
}
  
  var a = foo(5);
  console.log(a.next()) // Object{value:6, done:false}
  console.log(a.next()) // Object{value:NaN, done:false}
  console.log(a.next()) // Object{value:NaN, done:true}
  
  var b = foo(5);
  console.log(b.next()) // { value:6, done:false }
  console.log(b.next(12)) // { value:8, done:false }
  console.log(b.next(13)) // { value:42, done:true }

三、Generator函数的数据交换和错误处理

Generator函数可以暂停执行和恢复执行,它能够封装异步任务的根本原因。

generator函数支持for 和of循环:

function* foo(x) {
    yield (x + 1);
    yield (x / 3);
    yield a = () => {
        console.log('jj')
    }
    return x;
  }
  
var a = foo(5);
for (var i of a) {
    console.log(i)
}
// 6
// 1.6666666666666667
// [Function: a]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值