Asynchronous(异步处理-Generator)

Generator 是 ES6 标准中的异步编程方式
    通俗来讲 Generator 是一个带星号的“函数”(它并不是真正的函数,下面的代码会为你验证),可以配合 yield 关键字来暂停或者执行函数。
Generator(生成器)
    Generator 也是一种异步编程解决方案,它最大的特点就是可以交出函数的执行权,
    Generator 函数可以看出是异步任务的容器,需要暂停的地方,都用 yield 语法来标注。
    Generator 函数一般配合 yield 使用,Generator 函数最后返回的是迭代器
  function* gen() {
    let a = yield 111;
    console.log(a);
    let b = yield 222;
    console.log(b);
    let c = yield 333;
    console.log(c);
    let d = yield 444;
    console.log(d);
  }
  let t = gen();
  t.next(1); // 第一次调用next函数时,传递的参数无效,故无打印结果 执行到 let a = yield 111; 即结束,console.log(a);未执行,所以未打印
  t.next(2); // a输出2;
  t.next(3); // b输出3;
  t.next(4); // c输出4;
  t.next(5); // d输出5;

// 第一次的 next 虽然执行了但是并未输出结果,后面的每次执行 next 会把参数传入然后打印出来,
// 等到最后一次 next 对应的 yield 执行完之后,控制台会打印 “{value: undefined, done: true}” 的输出结果,
// 标识该 Generator 函数已经执行完毕,即 done:true
function* gen() {
    console.log('enter');
    let a = yield 1;
    let b = yield (function () {
      return 2;
    })();
    return 3;
  }
  var g = gen(); // 阻塞住,不会执行任何语句
  console.log(typeof g); // 返回 object 这里不是 "function"
  console.log(g.next());
  console.log(g.next());
  console.log(g.next());
  console.log(g.next());
  // output:
  // { value: 1, done: false }
  // { value: 2, done: false }
  // { value: 3, done: true }
  // { value: undefined, done: true }

Yield

yield 同样也是 ES6 的新关键词,配合 Generator 执行以及暂停。
yield 关键词最后返回一个迭代器对象,该对象有 value 和 done 两个属性,其中 done 属性代表返回值以及是否完成。
yield 配合着 Generator,再同时使用 next 方法,可以主动控制 Generator 执行进度。
  function* gen1() {
    yield 1;
    yield* gen2();
    yield 4;
  }
  function* gen2() {
    yield 2;
    yield 3;
  }
  var g = gen1();
  console.log(g.next());
  console.log(g.next());
  console.log(g.next());
  console.log(g.next());
  // output:
  // { value: 1, done: false }
  // { value: 2, done: false }
  // { value: 3, done: false }
  // { value: 4, done: false }
  // {value: undefined, done: true}

// 使用 yield 关键词的话还可以配合着 Generator 函数嵌套使用,从而控制函数执行进度。
// 这样对于 Generator 的使用,以及最终函数的执行进度都可以很好地控制,从而形成符合你设想的执行顺序。
// 即便 Generator 函数相互嵌套,也能通过调用 next 方法来按照进度一步步执行

Thunk 函数

接收一定的参数,会生产出定制化的函数,最后使用定制化的函数去完成想要实现的功能
  let isString = (obj) => {
    return Object.prototype.toString.call(obj) === '[object String]';
  };
  let isFunction = (obj) => {
    return Object.prototype.toString.call(obj) === '[object Function]';
  };
  let isArray = (obj) => {
    return Object.prototype.toString.call(obj) === '[object Array]';
  };
  let isType = (type) => {
    return (obj) => {
      return Object.prototype.toString.call(obj) === `[object ${type}]`;
    };
  };


  let isString = isType('String');
  let isArray = isType('Array');
  isString('123'); // true
  isArray([1, 2, 3]); // true

Generator 和 thunk 结合

  const readFileThunk = (filename) => {
    return (callback) => {
      fs.readFile(filename, callback);
    };
  };
  const gen = function* () {
    const data1 = yield readFileThunk('1.txt');
    console.log(data1.toString());
    const data2 = yield readFileThunk('2.txt');
    console.log(data2.toString);
  };

  let g = gen();
  g.next().value((err, data1) => {
    g.next(data1).value((err, data2) => {
      g.next(data2);
    });
  });

  // 很多层的嵌套,可读性不强
// 改进后

  function run(gen) {
    const next = (err, data) => {
      let res = gen.next(data);
      if (res.done) return;
      res.value(next);
    };
    next();
  }
  run(g);

Generator 和 Promise 结合

  // 最后包装成 Promise 对象进行返回
  const readFilePromise = (filename) => {
    return new Promise((resolve, reject) => {
      fs.readFile(filename, (err, data) => {
        if (err) {
          reject(err);
        } else {
          resolve(data);
        }
      });
    }).then((res) => res);
  };
  // 这块和上面 thunk 的方式一样
  const gen = function* () {
    const data1 = yield readFilePromise('1.txt');
    console.log(data1.toString());
    const data2 = yield readFilePromise('2.txt');
    console.log(data2.toString);
  };
  // 这块和上面 thunk 的方式一样
  function run(gen) {
    const next = (err, data) => {
      let res = gen.next(data);
      if (res.done) return;
      res.value.then(next);
    };
    next();
  }
  run(g);

co 函数库

co 函数库是著名程序员 TJ 发布的一个小工具,用于处理 Generator 函数的自动执行。
核心原理其实就是上面讲的通过和 thunk 函数以及 Promise 对象进行配合,包装成一个库.
co 函数库可以自动执行 Generator 函数,它的处理原理是什么呢?

    1.因为 Generator 函数就是一个异步操作的容器,它需要一种自动执行机制,co 函数接受 Generator 函数作为参数,并最后返回一个 Promise 对象。
    2.在返回的 Promise 对象里面,co 先检查参数 gen 是否为 Generator 函数。如果是,就执行该函数;如果不是就返回,并将 Promise 对象的状态改为 resolved。
    3.co 将 Generator 函数的内部指针对象的 next 方法,包装成 onFulfilled 函数。这主要是为了能够捕捉抛出的错误。
    4.关键的是 next 函数,它会反复调用自身。```

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值