js 之 Generator

Generator

Generator 函数是 ES6 提供的一种异步编程解决方案,它返回的就是一个 Iterator 结构,同时它是 async/await 的底层。

基本语法

function* gen() {
  yield 1;
  yield 2;
  yield 3;
  return 4;
}
const genIt = gen();
genIt.next(); // {value: 1, done: false}
genIt.next(); // {value: 2, done: false}
genIt.next(); // {value: 3, done: false}
genIt.next(); // {value: 4, done: true}
genIt.next(); // {value: undefined, done: true}

上面的代码定义了一个 Generator 函数 gen ,它与正常的函数的区别仅仅是在 function 后面紧跟了一个 * (不是规范一定要如此,但是推荐。也可以 function *),js 通过这个标识识别这是一个 Generator 函数,所以它内部可以实现其他函数无法实现的功能。

yield 关键字,函数执行的时候,遇到这个关键字就会停止,直到手动的调用 next()

通过上面的例子:

  1. 调用 Generator 函数时,函数并不会立即执行,而是一个指向内部状态的指针对象;
  2. 第一次调用 next 方法后,开始执行函数,遇到第一个 yield 后,停止执行,并将 yield 后面的计算式计算出结果并返回;
  3. 再一次调用 next 后,从上一次执行停止的地方开始执行,直到遇到下一个 yield;
  4. 直到执行完成,或者遇到 return 后停止;
  5. 它的执行逻辑与 遍历器对象(Iterator Object) 相同。

next 方法

Generator 函数通过 yield 关键字来暂停内部代码运行位置;通过 next() 方法,将指向内部状态的指针继续运行。当调用 next() 后,将指针所在位置的 yield 后面的数据返回。

function* demo() {
  let i = 0;
  while (i >= 0) {
    yield i;
    i++;   
  }
}

const it = demo();

console.log(it.next()); // { value: 0, done: false }
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }

yield 作为表达式时

yield 还可以当作表达式参与运算, 此时 yield 整块内容需要加上括号;与之对应的,此时调用 next(param) 方法需要添加参数,而参数 param 会在执行时,代替 (yield xxx) 在代码中执行。

  1. next 入参示例:

如果 yield 参与到计算中,需要加括号。

function* demo() {
  var a = 1;
  var b = 2;
  var num = 2 * (yield a + b);
}

var demoIt = demo()
demoIt.next(4); // 此时,var num = 2 * (yield a + b) === var num = 2 * 4
  1. 复杂示例。
function* gen(i) {
  var a = yield i + 1;
  var b = 2 * (yield (a + 1));
  var c = yield (b / 2);
  return (a + b + c);
}

var genIt = gen(2);; // 此时代码不执行,仅仅拿到指向内部状态的指针,并让 i = 2;
genIt.next(); // 返回 {value: 3, done: false}; 其中 value = i + 1;
gen.next(4);; // 返回 {value: 5, done: false}; 其中 a = (yield i + 1) = 4;
gen.next(2);; // 返回 {value: 2, done: false}; 其中 b = 2 * (yield (a + 1)) = 2 * 2 = 4
gen.next(4);; // 其中 c = yield (b / 2) = 4; 返回 {value: 12, done: true};  所以 value=  4 + 4 + 5

Iterator 的关系

Generator 函数执行后,返回一个遍历器对象。该对象本身也具有Symbol.iterator属性,执行后返回自身。

function* gen(){
  // some code
}

var g = gen();

g[Symbol.iterator]() === g

async/await 的关系

async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。

function* gen() {
  yield 1;
  yield 2;
}

async function asyncDemo() {
  await xxx;
  await xxx;
}
优点
  1. async/await 具有更好的语义化;
  2. async/await 具有内置的执行器,不需要手动执行;
  3. async/await 返回值是 Promise,可以用 .then 操作。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值