为什么 yield 不能 resolve promise?
Why can yield not resolve promise?
我有以下代码:
object = {
getPastEvents: () => Promise.resolve([1,2,3])
}
function* fetchPastEvents() {
const values = yield object.getPastEvents()
console.log(values)
}
const events = fetchPastEvents()
events.next()
events.next()
现在我想知道如何创建函数 getPastEvents
,returns 已定义 values
。现在,values
是 undefined
。我认为 yield 可以解决像 async await 这样的承诺。
当您调用 .next
时,您会恢复 运行 生成器函数。如果你想用一个特定的值恢复它,你将一个值传递给 .next
。因此,如果你想复制 redux-saga 解决承诺然后恢复生成器的行为,你需要接受第一次调用 .next
产生的承诺,等待承诺通过使用它的 [=14 来解决=] 方法,然后用它解析到的值调用 .next
。
const object = {
getPastEvents: () => Promise.resolve([1,2,3])
}
function* fetchPastEvents() {
console.log("entry")
const values = yield object.getPastEvents()
console.log(values)
}
const iterator = fetchPastEvents()
const promise = iterator.next().value;
promise.then(val => iterator.next(val))
我建议您不要自己这样做。如果这是你所说的传奇,那么 运行 通过 redux 传奇,你将免费获得这种行为。或者正如其他人所提到的,co 库实现了类似的功能。
I thought that yield can resolve a promise like async await.
不,yield
用于 yielding 一个 generator 函数 这意味着它会在该点停止函数执行, returns 右侧的表达式到 .next()
的调用者,然后将传递给下一个 .next(value)
调用的值继续执行。这在某种程度上是异步的,但与 async
/ await
无关。但是,您可以产生一个承诺,并在承诺解决时调用下一个 .next(value)
:
async function co(generator) {
let iterator = generator();
let done, value;
do {
({ done, value } = iterator.next(await value);
} while(!done);
return value;
}
可用作:
co(function* doAsync() {
let result = yield somePromise();
console.log(result);
});
但我不知道这有什么用,特别是因为现在有专门针对该用例的异步生成器。
在生成器中使用 yield 并不能保证等到 promise 被完全填充。
为了使您的示例有效,您必须编写代码来调用实现可迭代协议的对象的 next 方法。
function runGenerator(asyncGen) {
const gen = asyncGen();
let returnValue;
(function iterate(value){
returnValue = gen.next(value);
if(!returnValue.done) {
returnValue.value.then(iterate);
}
})();
}
const object = {
getPastEvents: () => Promise.resolve([1,2,3])
};
runGenerator(function*() {
const values = yield object.getPastEvents();
console.log(values);
});
请注意,这只是简单的实现,如果要在实际项目中使用,还需要检查更多条件。
我建议使用 co 模块,而不是仅仅为此实现自己的模块。
请注意,Async 和 Await 与此方法非常相似,它们都需要 promisified API。
但是要使用 Async & Await,请确保您的 JavaScript 引擎支持,否则您必须转译才能使它们在旧引擎中工作。
但是使用生成器将适用于大多数现代 JavaScript 引擎,它有点旧规范 (ES6)。
此外,通常转译 Async 和 Await 会生成大量代码,如果您想将内容保存得尽可能小,这可能会成为问题。
ES6 Generator 和 ES7 Async & Await 的主要区别是 ES6 Generator 不能使用 "Arrow function" 这在某些情况下非常关键(你必须在进入生成器之前在某处保存 "this" 引用函数的上下文),但是 ES7 异步函数可以做到这一点。
请注意,ES7 Async & Await 只是 promise 的语法糖 API,但 ES6 生成器不是。
我有以下代码:
object = {
getPastEvents: () => Promise.resolve([1,2,3])
}
function* fetchPastEvents() {
const values = yield object.getPastEvents()
console.log(values)
}
const events = fetchPastEvents()
events.next()
events.next()
现在我想知道如何创建函数 getPastEvents
,returns 已定义 values
。现在,values
是 undefined
。我认为 yield 可以解决像 async await 这样的承诺。
当您调用 .next
时,您会恢复 运行 生成器函数。如果你想用一个特定的值恢复它,你将一个值传递给 .next
。因此,如果你想复制 redux-saga 解决承诺然后恢复生成器的行为,你需要接受第一次调用 .next
产生的承诺,等待承诺通过使用它的 [=14 来解决=] 方法,然后用它解析到的值调用 .next
。
const object = {
getPastEvents: () => Promise.resolve([1,2,3])
}
function* fetchPastEvents() {
console.log("entry")
const values = yield object.getPastEvents()
console.log(values)
}
const iterator = fetchPastEvents()
const promise = iterator.next().value;
promise.then(val => iterator.next(val))
我建议您不要自己这样做。如果这是你所说的传奇,那么 运行 通过 redux 传奇,你将免费获得这种行为。或者正如其他人所提到的,co 库实现了类似的功能。
I thought that yield can resolve a promise like async await.
不,yield
用于 yielding 一个 generator 函数 这意味着它会在该点停止函数执行, returns 右侧的表达式到 .next()
的调用者,然后将传递给下一个 .next(value)
调用的值继续执行。这在某种程度上是异步的,但与 async
/ await
无关。但是,您可以产生一个承诺,并在承诺解决时调用下一个 .next(value)
:
async function co(generator) {
let iterator = generator();
let done, value;
do {
({ done, value } = iterator.next(await value);
} while(!done);
return value;
}
可用作:
co(function* doAsync() {
let result = yield somePromise();
console.log(result);
});
但我不知道这有什么用,特别是因为现在有专门针对该用例的异步生成器。
在生成器中使用 yield 并不能保证等到 promise 被完全填充。
为了使您的示例有效,您必须编写代码来调用实现可迭代协议的对象的 next 方法。
function runGenerator(asyncGen) {
const gen = asyncGen();
let returnValue;
(function iterate(value){
returnValue = gen.next(value);
if(!returnValue.done) {
returnValue.value.then(iterate);
}
})();
}
const object = {
getPastEvents: () => Promise.resolve([1,2,3])
};
runGenerator(function*() {
const values = yield object.getPastEvents();
console.log(values);
});
请注意,这只是简单的实现,如果要在实际项目中使用,还需要检查更多条件。
我建议使用 co 模块,而不是仅仅为此实现自己的模块。
请注意,Async 和 Await 与此方法非常相似,它们都需要 promisified API。
但是要使用 Async & Await,请确保您的 JavaScript 引擎支持,否则您必须转译才能使它们在旧引擎中工作。
但是使用生成器将适用于大多数现代 JavaScript 引擎,它有点旧规范 (ES6)。
此外,通常转译 Async 和 Await 会生成大量代码,如果您想将内容保存得尽可能小,这可能会成为问题。
ES6 Generator 和 ES7 Async & Await 的主要区别是 ES6 Generator 不能使用 "Arrow function" 这在某些情况下非常关键(你必须在进入生成器之前在某处保存 "this" 引用函数的上下文),但是 ES7 异步函数可以做到这一点。
请注意,ES7 Async & Await 只是 promise 的语法糖 API,但 ES6 生成器不是。