返回由链接的javascript承诺创建的对象

时间:2016-05-06 12:35:14

标签: javascript ionic-framework angular promise ionic2

我正在努力将我的脑袋缠绕在一起,以实现预期的结果。

简要背景: 我使用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'得到一个完整的对象。

非常感谢。

2 个答案:

答案 0 :(得分:1)

我会利用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;
  });
}

答案 1 :(得分:1)

您可以进行两项更改:

  1. 请记住then会返回新的承诺。由于您已经获得了db.getEventWithCMSID的承诺,因此您根本不需要使用new Promise,只需使用您在该then上调用的那个。一般来说,在达到new Promise之前,请考虑您是否已经有一份工作。

  2. 要等待所有下属操作完成,请使用Promise.all

  3. 所以:

    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失败会发生什么)。

    Live Example on Babel's REPL demonstrating failure