生成器在等待promise解析时返回未定义的值
Generator returns undefined for a value while waiting on promise to resolve
我有一个函数connectImpl在多个地方引用。我试图调用这个承诺,并通过生成器的中介同步地将其值返回给调用函数。如果我在生成器上调用。next(),它将以挂起状态返回
{ value: { state: 'pending' }, done: false }
我想等待这个生成器的值,直到它不再挂起。我已经尝试了多个版本的waitOn来完成这个任务,但我似乎不能使它正常工作。
我愿意接受实施建议。这让我有点抓狂。令人惊讶的是,最终创建的承诺日志稍后会在执行链中触发——在生成器完成之后。我显然遗漏了一些东西:
let models = null ;
let connectImpl = function() {
console.log('connectImpl')
let orm = setupImpl()
let config = getConfigImpl()
let qInitialize = q.nbind(orm.initialize, orm)
if(models) {
console.log('connectImpl:cached')
return q(models)
} else {
console.log('connectImpl:create')
return qInitialize(config).then(function(m){
console.log('connectImpl:created')
models = m
return models
})
}
}
let waitOn = function(generator){
console.log('waitOn')
let done = false ;
let generatorValue = null
while(!done){
var generatorResult = generator.next()
console.log(generatorResult)
done = generatorResult.done
generatorValue = generatorResult.value
}
return generatorValue
}
let domainImpl = function() {
console.log('domainImpl')
let getConnection = function *() {
console.log('domainImpl:getConnection')
yield connectImpl()
}
var generator = getConnection()
return waitOn(generator)
}
console.log('START')
console.log(domainImpl())
console.log('END')
我能够调用并获得
START
domainImpl
waitOn
domainImpl:getConnection
connectImpl
connectImpl:create
{ value: { state: 'pending' }, done: false }
{ value: undefined, done: true }
undefined
END
connectImpl:created
我可以添加执行connectImpl承诺,通过这个函数与中间件一起工作-但我似乎不能适应我的上述用例:
let domainMiddlewareImpl = function () {
return function *(next) {
let models = yield connectImpl()
this.request.models = models.collections;
this.request.connections = models.connections;
yield next
};
};
这看起来很有趣。让我们看看如何兑现承诺。我们的最终目标是这样写:
waitOn(function*(){
console.log("hello");
yield Q.delay(2000); // a placeholder, your calls in your example
console.log("World"); // this should run two seconds late.
});
你在这里的问题是你没有提前等待他们就放弃了他们。首先,你可以跳到最后找到一个"现成的"解决方案(不要!),这里是我们正在制作的一个小提琴。让我们通过生成器来实现waitOn:
让我们开始:
function waitOn(gen){
}
所以,我们的函数接受一个生成器,我们要做的第一件事就是调用它,因为我们需要执行生成器来获得结果:
function waitOn(gen){
let sequence = gen(); // call the generator
}
接下来,我们想把所有东西都包装在一个Promise中,因为我们的waitOn
将产生Promise并返回一个正在完成的Promise:
function waitOn(gen){
let sequence = gen(); // call the generator
return Promise.resolve(); // this is Q.resolve with Q
}
现在,我们有哪些情况:
- 生成器完成并返回一个值——
return
- 生成器产生一个常规值,我们不必等待它
- 生成器产生了一个承诺,我们必须等待它。我们还必须处理异常(如果我们产生一个拒绝的承诺怎么办?)
function waitOn(gen){
let sequence = gen(); // call the generator
return Promise.resolve().then(function cont(value){
let {value, done} = en.next(value); // get the next item
// depending on the case do what's appropriate
});
}
注意解构赋值-我认为这是可以的,因为你的代码中也有ES6语句。注意,由于这是第一次调用,value
是未定义的,但通常我们希望传递上次调用的值。现在来处理这些情况:
function waitOn(gen){
let sequence = gen(); // call the generator
return Promise.resolve().then(function cont(value){
let {done, value} = en.next(value); // get the next item
if(done) return value; // return case
if(!value || !value.then) return cont(value); // value case, recurse
return value.catch(e => gen.throw(e)).then(cont); // promise case
});
}
注意.catch
子句-我们将我们的代码从承诺扔回生成器,以便它处理,所以我们可以尝试/捕获承诺。
就是这样!在9行JavaScript中,我们实现了承诺生成器。现在,对于代码,您可以生成任何承诺:
let conn = q.nBind(orm.initialize, orm);
waitOn(function*(){
console.log("Starting")
let handle = yield conn(config);
console.log("Handle created!", handle); // connected here
});
快乐编码,享受协程的力量。在我们玩得开心之后——值得一提的是,Q已经发布了Q.async
和其他更新的承诺库,如蓝鸟发布了自己的Promise.coroutine
。如果你正在使用promise库,你可以使用它们。这个实现也适用于本地承诺。
- 这.SOMETHING 总是返回未定义的 - extjs
- React+Meteor:this.ops返回未定义
- 解析-为什么user.getSessionToken()返回未定义的结果
- Javascript函数返回未定义
- JavaScript-获取数据属性的值返回未定义的值
- .val()返回未定义的.text返回随机代码
- 为什么innerHTML返回“未定义”
- "这个“;正在返回未定义的
- 谷歌地图:函数返回未定义的值在console.log中运行良好
- Javascript json返回未定义
- importScripts在web工作程序中返回未定义的
- 访问嵌套 json 对象的属性将返回未定义
- NativeAppEventEmitter返回未定义的
- 我的函数返回“未定义”
- 新手Javascript函数返回未定义的石头剪刀游戏
- Nodejs模块函数返回未定义的,而不是异步的
- .getElementById在.createTextNode中返回未定义
- javascript函数不返回未定义的值
- Typeahead的Javascript类型返回未定义
- Javascript可见元素返回未定义