如果你使用return语句而不是yield,我很难找到会发生什么。
function *gen(){
const val = yield someAsyncFn();
assert.equal(val,4);
return val;
}
退货的收益与收益率有何不同?我假设return作为一个普通的return语句,但是生成器函数的上下文,它是否也调用gen.return()
?有点令人困惑。
也许以上只是与此相同?
function *gen(){
const val = yield someAsyncFn();
assert.equal(val,4);
yield val;
}
答案 0 :(得分:17)
return
为迭代器的最后一次迭代提供了一个返回值(当done
等于true
时)。
我已经简化了您的示例,因为异步操作似乎与问题无关:
function *gen(){
const val = yield 4;
return val * 2;
}
var it = gen();
var val = it.next(); // { value: 4, done: false }
console.log(val.value); // 4
var res = it.next(val.value); // { value: 8, done: true }
console.log(res.value); // 8
如果没有return
值,在最后一次迭代中,您将返回undefined
的值:
function *gen2(){
const val = yield 4;
yield val * 2;
}
var it2 = gen2();
var val2 = it2.next(); // { value: 4, done: false }
console.log(val2.value); // 4
var res2 = it2.next(val2.value); // { value: 8, done: false }
console.log(res2.value); // 8
it2.next(); // { value: undefined, done: true }
旁注:根据经验,总有一个next
调用,然后有yield
个语句,这就是为什么还有一个下一个调用的原因。第二个例子。
让我们说你使用像co
这样的生成器运行器,然后在完成生成器后得到的值就是return
的值:
co(function* () {
var result = yield Promise.resolve(true);
return result;
}).then(function (value) {
console.log(value); // value equals result
}, function (err) {
console.error(err.stack); // err equals result
});
重要提示:如果您正在迭代迭代器,使用for ... of
循环或Array.from
之类的东西,return
值将被忽略(由于您正在进行异步操作,因此可能并非如此):
function *gen(){
const val = yield 4;
return val * 2;
}
for (let value of gen()) {
console.log(value);
}
// 4
最后,调用生成器只会创建一个interator。迭代器返回的最终值是否相关,完全取决于您如何使用它。
答案 1 :(得分:2)
除了@nils的详尽回答外,还有另一种方法来捕获生成器函数的返回值,即yield*
的值(必须在另一个生成器函数内部):
function* arrayGenerator(arr) {
for (const element of arr)
yield element
return arr.length
}
function* elementsFollowedByLength(arr) {
const len = yield* arrayGenerator(arr);
yield len;
}
请注意,在生成数组元素之后,第一个生成器函数将返回一个值。
第二个生成器函数通过yield*
导致第一个生成器函数产生其所有值。当第一个生成器函数完成并返回时,该返回值将成为yield*
表达式的值。