你可以将Generators认为是可以中断进程、恢复进程的代码段,like this:
function* genFunc() {
// (A)
console.log('First');
yield;
console.log('Second');
}
function*
是一个新的Generators函数的关键字。yield
是一个可以暂停它自己的操作符。yield
接收和发送。genFunc()
时,您将获得可用于控制进程的生成器对象genObj:const genObj = genFunc();
Generators are defined with function*
.
function* foo(x) {
yield x + 1;
var y = yield null;
return x + y;
}
结果:
var gen = foo(5);
gen.next(); // { value: 6, done: false }
gen.next(); // { value: null, done: false }
gen.send(2); // { value: 7, done: true }
把这个方法贴到在线编辑器上运行了一下,打印出来的的
y = 2
,我就很不解,然后找了找资料,才得知:<u
·var y = yield; or var yield null;
使用来接收.next(参数)方法中的参数的,也就是:这个参数传入生成器中,作为上一个阶段异步任务的返回结果,被函数体内的变量y接收。</u>
另外一个例子:
function* foo(x) {
yield x+1;
var y = yield;
console.log(`y=${y}`);
return x + y ;
}
var gen = foo(5);
console.log(gen.next());
console.log(gen.next());
console.log(gen.next(4));
结果:
Object {
"done": false,
"value": 6
}
Object {
"done": false,
"value": undefined
}
"y=4"
Object {
"done": true,
"value": 9
}
Notes:
yield
is allowed anywhere an expression is. This makes it a powerful construct for pausing a function in the middle of anything, such as foo(yield x, yield y), or loops.-- 翻译的不好,直接上原文。
function* genFunc() { ··· }
const genObj = genFunc();
const genFunc = function* () { ··· };
const genObj = genFunc();
const obj = {
* generatorMethod() {
···
}
};
const genObj = obj.generatorMethod();
class MyClass {
* generatorMethod() {
···
}
}
const myInst = new MyClass();
const genObj = myInst.generatorMethod();
function fetchJson(url) {
return fetch(url)
.then(request => request.text())
.then(text => {
return JSON.parse(text);
})
.catch(error => {
console.log(`ERROR: ${error.stack}`);
});
}
上下是等价的
// es6
const fetchJson = co.wrap(function* (url) {
try {
let request = yield fetch(url);
let text = yield request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
});
// ECMAScript 2017
async function fetchJson(url) {
try {
let request = await fetch(url);
let text = await request.text();
return JSON.parse(text);
}
catch (error) {
console.log(`ERROR: ${error.stack}`);
}
}
yield
都可以通过next()
返回一个数据,所以可以通过循环或者递归生成很多数据。yield
可以通过next()
返回数据,那么就可以在收到下一个数据之前暂停,来消费这些数据,然后再恢复继续接收数据。function* genFunc() {
yield 'a';
yield 'b';
}
调用结果:
> const genObj = genFunc();
> genObj.next()
{ value: 'a', done: false }
> genObj.next()
{ value: 'b', done: false }
> genObj.next() // done: true => end of sequence
{ value: undefined, done: true }
function* genFunc() {
['a', 'b'].forEach(x => yield x); // SyntaxError
}
function* genFunc() {
for (const x of ['a', 'b']) {
yield x; // OK
}
}
写在后面
GitHub上集大家之力搞了一个前端面试题的项目,里面都是大家面试时所遇到的题以及一些学习资料,有兴趣的话可以关注一下。如果你也有兴趣加入我们的话,请在项目中留言。项目同时也可以在gitbook上查看。