• Promise && Generator


    再仔细地学一遍Promise Generator

    1. 生成器函数 返回一个迭代器

    const generatorFunction = function* () {};
    const iterator = generatorFunction();
    console.log(iterator[Symbol.iterator]);
    // function [Symbol.iterator()]
    

    2. 迭代器什么也不会执行

    const generatorFunction = function* () {
      console.log("a");
    };
    
    console.log(1);
    const iterator = generatorFunction();
    console.log(2);
    // 1
    // 2
    

    3.. next()方法用于推进生成器体的执行:

    const generatorFunction = function* () {
      console.log("a");
    };
    
    console.log(1);
    const iterator = generatorFunction();
    console.log(2);
    iterator.next();
    console.log(3);
    
    // 1
    // 2
    // a
    // 3
    

    4. next()方法返回一个对象,该对象指示迭代的进展:

    const generatorFunction = function* () {};
    const iterator = generatorFunction();
    console.log(iterator.next());
    // Object {value: undefined, done: true}
    

    5. 生成器函数将使用yield关键字。yield暂停生成器的执行,并将控制权返回给迭代器。

    const generatorFunction = function* () {
      yield;
    };
    const iterator = generatorFunction();
    console.log(iterator.next());
    console.log(iterator.next());
    

    6. 挂起时,生成器不会阻塞事件队列:

    const generatorFunction = function* () {
      var i = 0;
      while (true) {
        yield i++;
      }
    };
    
    const iterator = generatorFunction();
    console.log(iterator.next);
    console.log(iterator.next);
    console.log(iterator.next);
    console.log(iterator.next);
    console.log(iterator.next);
    console.log(iterator.next);
    // Object {value: 0, done: false}
    // Object {value: 1, done: false}
    // Object {value: 2, done: false}
    // Object {value: 3, done: false}
    // Object {value: 4, done: false}
    // Object {value: 5, done: false}
    

    7. 将一个值传递给迭代器

    8 yield关键字可以将一个值返回给迭代器:

    const generatorFunction = function* () {
      yield "foo";
    };
    
    iterator = generatorFunction();
    console.log(iterator.next());
    console.log(iterator.next());
    
    // Object {value: "foo", done: false}
    // Object {value: undefined, done: true}
    

    9. 可以生成任何数据类型,包括函数、数字、数组和对象。当生成器被推进到完成时,返回值被返回。

    const generatorFunction = function* () {
      yield "foo";
      return "bar";
    };
    const iterator = generatorFunction();
    console.log(iterator.next());
    console.log(iterator.next());
    
    // Object {value: 'foo', done: false}
    // Object {value: 'bar}, done: true}
    

    10. yield关键字可以从迭代器返回一个值:

    const generatorFunction = function* () {
      console.log(yield);
    };
    const iterator = generatorFunction();
    iterator.next("foo");
    iterator.next("bar");
    // bar
    // 第一个foo不要了 值直接被丢弃 一开始在这里卡了一下 不理解
    // 现在的理解是这个样子的
    // yield会有一个返回值 第一个foo的返回值被第二个bar覆盖了,然后第一个foo就没有位置输出,输出的是bar
    

    11. 理解执行流程

    // 使用for of 迭代 迭代器

    let index;
    
    const foo = function* () {
      yield "foo";
      yield* bar();
    };
    const bar = function* () {
      yield "bar";
      yield* barz();
    };
    const baz = function* () {
      yield "baz";
    };
    
    for (index of foo()) {
      console.log(index);
    }
    
    // foo
    // bar
    // baz
    // 将生成器函数嵌套在另一个生成器当中执行实际上 与 将目标生成器函数的主体导入目标生成器相同
    // 上述代码等同于
    
    let index;
    
    const foo = function* () {
      yield "foo";
      yield "bar";
      yield "baz";
    };
    
    for (index of foo()) {
      console.log(index);
    }
    // foo
    // bar
    // baz
    

    12. 除了使用 next()推进生成器实例之外,您还可以throw()。抛出的任何东西都会传递回生成器的代码,也就是说,它可以在生成器实例内部或外部处理:

    const generatorFunction = function* () {
      while (true) {
        try {
          yield;
        } catch (e) {
          if (e != "a") {
            throw e;
          }
          console.log("Generator caught", e);
        }
      }
    };
    
    const iterator = generatorFunction();
    iterator.next();
    try {
      iterator.throw("a");
      itrrator.throw("b");
    } catch (e) {
      console.log("Uncaught", e);
    }
    // 所有的数据都能够被抛出,包括函数、数字、数组和对象
    

    13. 生成器函数解决了什么问题?

    // 地狱回调

    // tonic ^6.0.0
    const foo = (name, callback) => {
      setTimeout(() => {
        callback(name);
      }, 100);
    };
    
    foo("a", (a) => {
      foo("b", (b) => {
        foo("c", (c) => {
          console.log(a, b, c);
        });
      });
    });
    
    // a
    // b
    // c
    
    // 解决方法
    // tonic ^6.0.0
    (function* () {
      const a = yield curry(foo, "a");
      const b = yield curry(foo, "b");
      const c = yield curry(foo, "c");
    
      console.log(a, b, c);
    });
    
    // 要执行生成器,我们需要一个控制器。控制器需要完成异步请求并返回结果。
    const controller = (generator) => {
      const iterator = generator();
    
      const advancer = (response) => {
        // Advance the iterator using the response of an asynchronous callback.
        const state = iterator.next(response);
    
    ​    if (!state.done) {
    ​      // Make the asynchronous function call the advancer.
    ​      state.value(advancer);
    ​    }
      };
    
      advancer();
    };
    

    14.promise 三个用途

    用途 1. Linear build tests for async tool

    watch({}, function* (compilation) {
      yield compilation(); // pause and wait
      t.false(fs.readdirSync("./node_modules").includes("lodash"));
    
      // make changes
      const packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
      packageJson.dependencies.lodash = "*";
      fs.writeFileSync("package.json", JSON.stringify(packageJson, null, 2));
    
      yield compilation(); // pause and wait
      // assert they were reflected
      t.true(fs.readdirSync("./node_modules").includes("lodash"));
      t.end();
    });
    

    用途 2. co

    co is a generator interpreter which allows you to write nicer, more linear code for promises.

    // Instead of this nested code:
    getUser().then((user) => getComments(user));
    
    // You have this:
    co(function* () {
      const user = yield getUser();
      const comments = yield getComments(user);
    });
    

    用途 3.redux saga

    这个是用的比较多的 来详细的写一下

    在Redux架构中管理副作用是一件轻而易举的事情。

    在一个叫做saga的program中,将逻辑上相关的行为片段分组,而不是分散在许许多多的creatos和reducers,用过原生redux库的都知道,要么把reducer与action写在一起,要么被分开写时文件来回切换倒腾 折腾死。

    redux-saga有许多的command,使用最多的有以下几个

    • take(ACTION_NAME) —— 等待一个名为ACTION_NAME的action被dispatched,然后return 一个 action object
    • put(action)—— dispatch 一个action
    • call(promiseFn)—— class a function that returns a promise, and waits for it to resolve, Returns what the promise resolved to
    • &others
  • 相关阅读:
    Erlang性能的八个误区
    Unity预览
    一步步实现cnblogs博客采集工具>实现辅助对话框
    Asp.Net MVC 必备插件MVC Route Visualizer(Visual Studio 2012 版)
    IBM SOA[ESB,BPM,Portal等]基础架构图解
    PowerShell收发TCP消息包
    Sonar安装使用篇
    在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
    排序算法
    ASP.NET MVC Web API 学习增删改查
  • 原文地址:https://www.cnblogs.com/ssaylo/p/12800319.html
Copyright © 2020-2023  润新知