再仔细地学一遍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