这是我的代码,我希望从顶部开始,执行将继续下去。前两个子句从数据库中获取记录,然后更新“self”对象。但是,当执行命中Q.all时,该方法返回Promises而不是实际解析promise并将值放入loc(最终是'self')。最终,承诺将得到解决,但在后面的子句中返回'self self'。我需要在'return self'运行之前设置self.locations。
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
return self.loadClientAppImpl(data);
}).then(function() {
locArray = self.app.field_194_raw;
return dao.getChildren("object_23", self.appId, "field_210", "field_164").then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
});
}).then(function() {
var locPromiseArray = getPromisesArray(locArray);
return Q.all(locPromiseArray).then(function(locs){
self.locations = locs;
});
}).then(function() {
return self;
}).done();
我认为多重承诺应该像单一呼叫承诺一样?
即。 dao.getRecords很好,但为什么Q.all([dao.getRecords1,dao.getRecord2等])不能正常工作(即在'return self;'之前没有解决)?
以下代码工作正常,我用一个承诺替换了Q.all,一切都按预期工作(即返回自己在链中称为last)。问题仍然存在:为什么Q.all的工作方式不一样?我假设这只是它应该工作的方式,我不了解实现。
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
self.loadClientAppImpl(data);
}).then(function() {
locArray = self.app.field_194_raw;
return dao.getChildren("object_23", self.appId, "field_210", "field_164").then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
});
}).then(function() {
var locPromiseArray = getPromiseArray(locArray);
return locPromiseArray[0].then(function(locs){
self.locations = locs;
});
}).then(function() {
return self;
}).done();
这是getPromisesArray方法
function getPromiseArray (locArray) {
var locationCollection = "object_22";
//create a promise for all of the records
var locationPromiseArray = [];
if(locArray[0]){
var locId0 = locArray[0].id;
//dao.getRecord returns a promise
locationPromiseArray.push(dao.getRecord(locationCollection, locId0));
}
if(locArray[1]){
var locId1 = locArray[1].id;
locationPromiseArray.push(dao.getRecord(locationCollection, locId1));
}
if(locArray[2]){
var locId2 = locArray[2].id;
locationPromiseArray.push(dao.getRecord(locationCollection, locId2));
}
if(locArray[3]){
var locId3 = locArray[3].id;
locationPromiseArray.push(dao.getRecord(locationCollection, locId3));
}
return locationPromiseArray;
};
感谢您的帮助!
标记
PS。我注意到下面的代码表现不同,我原本期望它的工作方式相同。开始怀疑我是否发现了一个bug。在第一种情况下,'结果'用值填充(应该是)。在第二种情况下,“结果”是一种承诺。它们不应该是这样或那样的吗?
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
self.loadClientAppImpl(data);
}).then(function() {
return dao.getChildren("object_23", self.appId, "field_210", "field_164");
}).then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
locPromiseArray = getPromiseArray(self.app.field_194_raw);
return Q.all(locPromiseArray).then(function(results){
self.locations = results;
return self;
});
});
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
self.loadClientAppImpl(data);
}).then(function() {
return dao.getChildren("object_23", self.appId, "field_210", "field_164");
}).then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
locPromiseArray = getPromiseArray(self.app.field_194_raw);
return Q.all(locPromiseArray);
}).then(function(results){
self.locations = results;
return self;
});
答案 0 :(得分:1)
很难理解为什么用Q.all(...)
替换单个承诺会得到所需的结果。您对正在发生的事情的分析可能是不正确的。
但是,这里有一些想法。
除非通过返回新的承诺或不同的值进行过滤,否则不需要中间链.then()
。一个中间链.then()
,它的回调只是做出一个贡献,是一个候选人。你有两个这样的任务。
这样的事情很容易出错,但我认为你的主要代码块会重新排列如下:
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
return self.loadClientAppImpl(data);
}).then(function() {
return dao.getChildren("object_23", self.appId, "field_210", "field_164");
}).then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
return Q.all(getPromisesArray(self.app.field_194_raw));
}).then(function(locs) {
self.locations = locs;
return self;
}).done();
请注意,赋值现在也在返回某些内容的函数中,重要的是self.locations = locs
与返回self
的函数相同。这可能会或可能不会解决您的问题,尽管它有希望 [原文如此]。
对于记录,getPromiseArray()
还应简化如下:
function getPromiseArray (locArray) {
return locArray.map(function(loc) {
return dao.getRecord("object_22", loc.id);
});
};
答案 1 :(得分:0)
事实证明答案很简单,它的全部内容都是关于返回类型以及如何设置promises,这对于Q来说就是传播,在这里讨论:
https://github.com/kriskowal/q
引用:
var outputPromise = getInputPromise()
.then(function (input) {
}, function (reason) {
});
如果在处理程序中返回一个值,则将完成outputPromise。
如果在处理程序中抛出异常,则会得到outputPromise 拒绝。
如果在处理程序中返回一个promise,则outputPromise将“变为”那个 诺言。能够成为新的承诺对于管理是有用的 延迟,结合结果或从错误中恢复。
以上是返回值或Promise的情况。关键是这个期待的来电者是什么?就我而言,它期待一个价值。当使用像这样的承诺(第一种情况)时,这是有效的:
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
self.loadClientAppImpl(data);
}).then(function() {
locArray = self.app.field_194_raw;
return dao.getChildren("object_23", self.appId, "field_210", "field_164").then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
});
}).then(function() {
var locPromiseArray = getPromiseArray(locArray);
return locPromiseArray[0].then(function(locs){
self.locations = [locs];
});
}).then(function() {
return self;
}).done();
'self'最终被返回,并且调用者很高兴,因为这是它所期望的,一个值。但是,使用以下代码(来自原始问题),不返回值,而是返回承诺(第二种情况):
return dao.getRecords(APP_COLLECTION, filters).then(function(data) {
return self.loadClientAppImpl(data);
}).then(function() {
locArray = self.app.field_194_raw;
return dao.getChildren("object_23", self.appId, "field_210", "field_164").then(function(knackRecord) {
self.priorCarriers = knackRecord.records;
});
}).then(function() {
var locPromiseArray = getPromisesArray(locArray);
return Q.all(locPromiseArray).then(function(locs){
self.locations = locs;
});
}).then(function() {
return self;
}).done();
即。当使用Q.all时,你得到一个需要解决的承诺,而在第一种情况下,返回self(一个值)。
我现在已经大大清理并优化了代码,但我希望为其他人关闭循环,以防它们可能有所帮助。
顺便说一句 - 从调用代码中可以轻松解决这种情况,Q提供了一种“何时”的方法,以便在您不确定是否收回Promise或值时使用/ p>return Q.when(valueOrPromise, function (value) {
}, function (error) {
});
我最终将这个用于测试这两种情况,并且可以看到'valueOrPromise'变量填充了值(第一种情况)或Promise(第二种情况)。
感谢所有为此做出贡献的人 - 欢呼!