返回由链式 javascript 承诺创建的对象
Returning objects created by chained javascript promises
我正在努力思考如何将承诺链接在一起以实现预期的结果。
简要背景:
我正在使用 Ionic2(基于 Angular2)创建移动应用程序。数据持久化基于 SQLite。为了重新构建包含嵌套数组的复杂对象,我需要将多个数据库调用链接在一起。
buildObjectFromID(id) {
return new Promise(function (resolve, reject) {
let db = new DBHelper();
try {
// Get the event object from id
db.getEventWithCMSID(id).then(event => {
db.getBannerForOwner(event.cmsId).then(banner => {
event.banner = banner;
});
db.getImagesForOwner(event.cmsId).then(images => {
event.images = images;
});
db.getProfilePicturesForOwner(event.cmsId).then(profilepictures => {
event.profilepicture = profilepictures;
});
db.getLogosForOwner(event.cmsId).then(logos => {
event.logos = logos;
});
resolve(event);
});
}
catch
(err) {
reject({err: err});
}
}
);
}
此方法旨在从数据库中获取一个主要对象,并使用它的 ID 从其他表中获取并附加其相关属性。我希望在返回结果之前重建整个对象。
但是,目前,对象被传回,然后随着时间的推移,一旦每次额外的调用完成,就会添加属性。
如果有人能告诉我如何将它们链接在一起,以便调用 'buildObjectFromID' 的控制器获得一个完整的对象,我将不胜感激。
非常感谢。
我会利用 Promise.all
方法并像这样链接不同的承诺:
buildObjectFromID(id) {
let db = new DBHelper();
// Get the event object from id
return db.getEventWithCMSID(id).then(event => {
return Promise.all([
event,
db.getBannerForOwner(event.cmsId),
db.getImagesForOwner(event.cmsId),
db.getProfilePicturesForOwner(event.cmsId),
db.getLogosForOwner(event.cmsId)
]);
}).then(result => {
let event = result[0];
let banner = result[1];
let images = result[2];
let logos = result[3];
event.banner = banner;
event.images = images;
event.profilepicture = profilepictures;
event.logos = logos;
return event;
});
}
您可以进行两项更改:
记住then
returns一个新的承诺。由于您已经从 db.getEventWithCMSID
获得了承诺,因此您根本不需要使用 new Promise
,只需使用通过调用 then
获得的承诺即可。一般来说,在达到 new Promise
之前,请考虑一下您是否已经有了一份工作。
要等待所有下属操作完成,请使用Promise.all
。
所以:
buildObjectFromID(id) {
let db = new DBHelper();
return db.getEventWithCMSID(id).then(event => {
return Promise.all([
db.getBannerForOwner(event.cmsId).then(banner => {
event.banner = banner;
}),
db.getImagesForOwner(event.cmsId).then(images => {
event.images = images;
}),
db.getProfilePicturesForOwner(event.cmsId).then(profilepictures => {
event.profilepicture = profilepictures;
}),
db.getLogosForOwner(event.cmsId).then(logos => {
event.logos = logos;
})
]).then(() => {
return event;
});
});
}
Live Example on Babel's REPL (为简洁起见,我省略了两个从属调用,仅包括横幅和图像)
这还具有传播失败的优势,这是您的原始代码没有做到的(例如,考虑如果 getBannerForOwner
失败会发生什么)。
我正在努力思考如何将承诺链接在一起以实现预期的结果。
简要背景: 我正在使用 Ionic2(基于 Angular2)创建移动应用程序。数据持久化基于 SQLite。为了重新构建包含嵌套数组的复杂对象,我需要将多个数据库调用链接在一起。
buildObjectFromID(id) {
return new Promise(function (resolve, reject) {
let db = new DBHelper();
try {
// Get the event object from id
db.getEventWithCMSID(id).then(event => {
db.getBannerForOwner(event.cmsId).then(banner => {
event.banner = banner;
});
db.getImagesForOwner(event.cmsId).then(images => {
event.images = images;
});
db.getProfilePicturesForOwner(event.cmsId).then(profilepictures => {
event.profilepicture = profilepictures;
});
db.getLogosForOwner(event.cmsId).then(logos => {
event.logos = logos;
});
resolve(event);
});
}
catch
(err) {
reject({err: err});
}
}
);
}
此方法旨在从数据库中获取一个主要对象,并使用它的 ID 从其他表中获取并附加其相关属性。我希望在返回结果之前重建整个对象。
但是,目前,对象被传回,然后随着时间的推移,一旦每次额外的调用完成,就会添加属性。
如果有人能告诉我如何将它们链接在一起,以便调用 'buildObjectFromID' 的控制器获得一个完整的对象,我将不胜感激。
非常感谢。
我会利用 Promise.all
方法并像这样链接不同的承诺:
buildObjectFromID(id) {
let db = new DBHelper();
// Get the event object from id
return db.getEventWithCMSID(id).then(event => {
return Promise.all([
event,
db.getBannerForOwner(event.cmsId),
db.getImagesForOwner(event.cmsId),
db.getProfilePicturesForOwner(event.cmsId),
db.getLogosForOwner(event.cmsId)
]);
}).then(result => {
let event = result[0];
let banner = result[1];
let images = result[2];
let logos = result[3];
event.banner = banner;
event.images = images;
event.profilepicture = profilepictures;
event.logos = logos;
return event;
});
}
您可以进行两项更改:
记住
then
returns一个新的承诺。由于您已经从db.getEventWithCMSID
获得了承诺,因此您根本不需要使用new Promise
,只需使用通过调用then
获得的承诺即可。一般来说,在达到new Promise
之前,请考虑一下您是否已经有了一份工作。要等待所有下属操作完成,请使用
Promise.all
。
所以:
buildObjectFromID(id) {
let db = new DBHelper();
return db.getEventWithCMSID(id).then(event => {
return Promise.all([
db.getBannerForOwner(event.cmsId).then(banner => {
event.banner = banner;
}),
db.getImagesForOwner(event.cmsId).then(images => {
event.images = images;
}),
db.getProfilePicturesForOwner(event.cmsId).then(profilepictures => {
event.profilepicture = profilepictures;
}),
db.getLogosForOwner(event.cmsId).then(logos => {
event.logos = logos;
})
]).then(() => {
return event;
});
});
}
Live Example on Babel's REPL (为简洁起见,我省略了两个从属调用,仅包括横幅和图像)
这还具有传播失败的优势,这是您的原始代码没有做到的(例如,考虑如果 getBannerForOwner
失败会发生什么)。