ES6知识点整理Generator的应用

Generator 函数是 一种异步编程解决方案,Generator 函数会返回一个遍历器对象,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式。

认识generator函数

function * fn() {
  console.log('hello');
  return 'Joh';
}
// 执行fn()时不会直接执行方法体中的代码,它会返回一个指针, 这个指针实现了 interator接口,也就是返回一个interator对象
let it = fn();
// 通过调用next就会执行方法体, 返回结果是 {value:'Joh', done:true}, 其中next返回的是函数体中return的值
let res = it.next();
console.log(res);

generator函数中的yield 与 return

function * fn() {
    // 和yield相配合,把一个generator内部分为几个断点来执行,每个断点就是yield语句
    // 注意 yield和return的区别: yield可以有多个,return只能有1个
    yield 1;
    yield 2;
    yield 3;
    return 4; // 可以没有return值,done为true的value将会是undefined
  }
  let it = fn();
  //for-of 循环中只能打印done为false的value值,done为true时,程序终止
  for(let v of it) {
    console.log(v); // 分别输出 1 2 3
  }

yield 的值与赋值语句

function * fn(_name) {
  let name = yield _name; // yield 的默认值为undefined
  return name;
}
let it = fn('Joh');
console.log(it.next()); // {value:'Joh', done:false}
console.log(it.next('Tom')); // {value:'Tom', done:true} // 此处value应该为undefined,但是通过next参数的形式赋值改变了最后一个值
console.log(it.next('Lily')); // {value: undefined, done:true} // 已经循环完毕,即使传值也是undefined

yield 语句的位置与括号

function sum(a, b) {
  return a + b;
}
function * fn() {
  let res = sum(yield 1, 5 + (yield 3));
  console.log(res);
  console.log('my qq: ' + (yield qq)); // yield 在一个语句中需要括起来
}
fn();

yield 异常捕获

异常捕获的方式1:

function * fn() {
  let qq = yield; // yield 默认返回undefined, 不会抛出异常
  console.log(qq);
}

let g = fn();
g.next(); // 第一个断点没有输出
// g.next('qq 11111'); // 完毕之后传值输出:qq 11111
g.throw('error!'); // Uncaught error!

异常捕获的方式2:

function * fn() {
  let qq;
  try {
    qq = yield; // yield 默认返回undefined
  }catch(e){
    console.log('qq have error');
  }finally{
    console.log(qq);
  }
}
let g = fn();
g.next();
g.throw('error!');
// qq have error
// undefined

异常捕获的方式3:

function * fn() {
  let qq;
  qq = yield;
  console.log(qq);
}
let g = fn();
g.next();
try{
  g.throw('error!');
}catch(e){
  console.log('qq have error!');
}

异常捕获的方式4:

function * fn() {
  let qq;
  try {
    qq = yield ff; // ff 未定义, 所以qq不会被正确赋值 此处是非 yield 的异常
  }catch(e){
    console.log('err1');
  }
  console.log(qq);
}
let g = fn();
g.next();
g.next('qq 5554');
// err1
// undefined

利用generator和promise结合使用,让异步的逻辑关系,使用同步的方式书写

function asyncF(name) {
  return new Promise(function(resolve){
    setTimeout(function(){
      resolve('my name is ' + name);
    });
  });
}

function * fn() {
  console.log(yield asyncF('Joh'));
}

let gf = fn();

function exec(gf,value) {
  let res = gf.next(value);
  if(!res.done) {
    if(res.value instanceof Promise) {
      res.value.then(function (v) {
        exec(gf, v);
      })
    }else{
      exec(gf, res.value);
    }
  }
}
exec(gf); // my name is Joh

更复杂的写法:

function asyncF(name) {
  return new Promise(function(resolve){
    setTimeout(function(){
      resolve('my name is ' + name);
    });
  });
}

function sum(a, b) {
  return new Promise(function (resolve) {
    setTimeout(function () {
        resolve(a + b);
    });
  })
}

function * fn(name) {
  if((yield sum(3,5)) > 6) {
    console.log(yield asyncF(name));
  }else{
    console.log('error');
  }
}

let gf = fn('Joh');

// generator 执行器 相当于 tj/co 模块
function exec(gf,value) {
  let res = gf.next(value);
  if(!res.done) {
    if(res.value instanceof Promise) {
      res.value.then(function (v) {
        exec(gf, v);
      })
    }else{
      exec(gf, res.value);
    }
  }
}
exec(gf); // my name is Joh

使用纯promise实现:

function asyncF(name) {
  return new Promise(function(resolve){
    setTimeout(function(){
      resolve('my name is ' + name);
    });
  });
}

function sum(a, b) {
  return new Promise(function (resolve) {
    setTimeout(function () {
        resolve(a + b);
    });
  })
}

function fn(name) {
  sum(3,5)
    .then(function (num) {
      if(num > 6) {
        asyncF(name)
          .then(function (v) {
            console.log(v);
          })
      }else{
        console.log('error');
      }
    })
}

fn('Joh');

使用co模块,来代替自己写的执行器

var co = require('co');

function asyncF(name) {
  return new Promise(function(resolve){
    setTimeout(function(){
      resolve('my name is ' + name);
    });
  });
}

function sum(a, b) {
  return new Promise(function (resolve) {
    setTimeout(function () {
        resolve(a + b);
    });
  })
}

function * fn(name) {
  if((yield sum(3,5)) > 6) {
    console.log(yield asyncF(name));
  }else{
    console.log('error');
  }
}

var fnx = co.wrap(fn);

fnx('Joh'); // my name is Joh
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值