【JavaScript】Generator函数

一、简介

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。

执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

二、基本用法

function * foo(x, y) {
    
     ··· }
function *foo(x, y) {
    
     ··· }
function* foo(x, y) {
    
     ··· }
function*foo(x, y) {
    
     ··· }

由于 Generator 函数仍然是普通函数,所以一般的写法是上面的第三种,即星号紧跟在 function 关键字后面。本书也采用这种写法。

该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象。

function* helloWorldGenerator() {
    
    
  yield 'hello';
  yield 'world';
  return 'ending';
}


var hw = helloWorldGenerator();
console.log(hw);
console.log(hw.next());
console.log(hw.next());
console.log(hw.next());
console.log(hw.next());

在这里插入图片描述
helloWorldGenerator返回的是一个指针对象,可以调用 next 方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个 yield 表达式(或 return 语句)为止。

换言之,Generator 函数是分段执行的, yield 表达式是暂停执行的标记,而 next 方法可以恢复执行。

三、next传参

yield表达式本身没有返回值,或者说总是返回 undefined 。
看一个例子:

function* add(x, y){
    
    
    let z = yield x + y;
    console.log('上一个yield的结果z是:', z);
    return z + 1;
}
const f = add(1, 2);
console.log(f.next());
console.log(f.next());
console.log(f.next());

在这里插入图片描述
可以看到,使用z来接收yield(x, y)的结果,发现是undefine。

next 方法可以带一个参数,该参数就会被当作上一个 yield 表达式的返回值
我们使用next带参数解决上面undefine问题。

function* add(x, y){
    
    
    let z = yield x + y;
    console.log('上一个yield的结果z是:', z);
    return z + 1;
}
const f = add(1, 2);
let z = f.next();
console.log(z);
console.log(f.next(z.value));
console.log(f.next());

在这里插入图片描述

四、Generator函数异步应用

ES6 诞生以前,异步编程的方法,大概有下面四种。

  1. 回调函数
  2. 事件监听
  3. 发布/订阅
  4. Promise 对象

Generator 函数将 JavaScript 异步编程带入了一个全新的阶段。

var fetch = require('node-fetch');


function* gen(){
    
    
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();

//result.value是一个promise实例
result.value.then(function(data){
    
    
  return data.json();
}).then(function(data){
    
    
  //继续执行generator函数,传入上次结果data
  g.next(data);
});

而es2017提出的async函数则是 Generator 函数的语法糖,使用async配合await使得异步操作变得更加方便。

猜你喜欢

转载自blog.csdn.net/ZHANGYANG_1109/article/details/126751384
今日推荐