Generator函数

从计算机角度看,生成器是一种类协程或半协程,它提供了一种可以通过特定语句或方法使其执行对象暂停的功能。Generator函数,返回一个部署了Iterator接口的遍历器对象,用来操作内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield语句后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
​ yield 关键字使生成器函数暂停执行,并返回跟在它后面的表达式的当前值。可以把它想成是return关键字的一个基于生成器的版本,但其并非退出函数体,而是切出当前函数的运行时,与此同时可以将一个值带到主线程中。yield语句是暂停执行的标记,而next方法可以恢复执行。

function* gen(){
  yield 'li';
  yield 'gang'; // 有误!!!
  return '!';
}
var g = gen();
g.next(); // {value: 'li', done: false}
g.next(); // {value: 'gang', done: false}
g.next(); // {value: '!', done: true}

1)遇到yield语句,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值;
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句;
(3)如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值;
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
需要注意的是,yield语句后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行,因此等于为JavaScript提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。

function* gen() {
  yield  123 + 456;
}
function* f() {
  console.log('执行了!')
}
let gen = f();
setTimeout(function () {
  gen.next()
}, 2000);

next方法的参数
​ 注意: yield句本身没有返回值(返回undefined)。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var a = foo(5);
a.next();  // Object{value:6, done:false}
a.next();  // Object{value:NaN, done:false}
a.next();  // Object{value:NaN, done:true}

var b = foo(5);
b.next();   // { value:6, done:false }
b.next(12); // { value:8, done:false }
b.next(13); // { value:42, done:true }

ext方法不带参数,导致y的值等于2 * undefined(即NaN),除以3以后还是NaN;next方法提供参数,第一次调用b的next方法时,返回x+1的值6;第二次调用next方法,将上一次yield语句的值设为12,因此y等于24,返回y/3的值8。
​ 注意:这个功能有很重要的语法意义。Generator函数从暂停状态到恢复运行,它的上下文状态(context)是不变的。通过next方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。也就是说,可以在Generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。

let g = f();
g.next() // { value: 0, done: false }
g.next() // { value: 1, done: false }
g.next(true) // { value: 0, done: false }
//for...of循环可以自动遍历Generator函数时生成的Iterator对象,且此时不再需要调用next方法。
    function *foo() {
      yield 1;
      yield 2;
      return 3;
    }
    for (let v of foo()) {
      console.log(v);
    }
    function* fibonacci() {
      let [prev, curr] = [0, 1];
      while (true) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
      }
    }
    for (let n of fibonacci()) {
      if (n > 1000) break;
      console.log(n);
    }
	//判断是否为Generator函数
	function isGenerator(fn){
	  // 生成器示例必带@@toStringTag属性
	  if(Symbol && Symbol.toStringTag) {
	    return fn[Symbol.toStringTag] === 'GeneratorFunction';
	  }
	}

async函数
​ async函数可以理解为Generator函数的语法糖,使用async内置了执行器,无需调用next方法进行逐步调用。且其返回值为Promise。

基本用法
​ async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

sync function gen(x){
    var y = await x + 2;
    var z = await y + 2;
    return z;
}
gen(1).then(result => console.log(result), error => console.log(error));
gen(1).then(result => console.log(result)).catch(error => console.log(error));
/*回调方式*/
function test(callback) {
  setTimeout(() => callback('hello world'), 5000);
}
var res = test((value) => console.log(value));
console.log(res);

/*Promise方式*/
function test() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      return resolve('hello world');
    }, 5000)
  });
}
test().then((value) => console.log(value));

/*async方式*/
async function test() {
  return await new Promise((resolve, reject) => {
    setTimeout(() => {
      return resolve('hello world');
    }, 5000)
  });
}
test().then((value) => console.log(value));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值