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
posted @ 2020-04-29 10:07  林来  阅读(176)  评论(0编辑  收藏  举报