【问题标题】:Returning objects created by chained javascript promises返回由链式 javascript 承诺创建的对象
【发布时间】:2016-05-06 12:35:13
【问题描述】:

我正在努力将我的头脑围绕着将承诺链接在一起以实现预期的结果。

背景简介: 我正在使用 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”的控制器获得一个完整的对象。

非常感谢。

【问题讨论】:

    标签: javascript ionic-framework angular promise ionic2


    【解决方案1】:

    您可以进行两项更改:

    1. 记住then 返回一个新的承诺。由于您已经得到了来自db.getEventWithCMSID 的承诺,因此您根本不需要使用new Promise,只需使用通过调用then 获得的那个。一般来说,在联系new Promise 之前,请考虑一下您是否已经有一个可以使用的。

    2. 要等待所有下属操作完成,请使用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 失败会发生什么)。

    Live Example on Babel's REPL demonstrating failure

    【讨论】:

    • 非常感谢 T.J. 的快速响应
    • 您的解决方案非常深入。我非常感激。这解决了我以正确顺序构建对象并返回完整对象的问题,但是,buildObjectFromID 的调用方法也是一个 Promise,我仍然遇到问题。我应该提出另一个问题,还是更新我的原始问题?
    • @PhillipHartin:很高兴有帮助。由于这是相当新的信息,并且已经有两个关于这个问题的答案,我想说你打开一个新问题的本能可能是最好的。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2023-01-27
      • 2020-01-04
      • 2013-09-15
      • 2017-03-13
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 2018-10-12
      • 1970-01-01
      相关资源
      最近更新 更多