Returning objects created by chained javascript promises

谁说胖子不能爱 提交于 2020-01-04 05:19:12

问题


I am struggling to wrap my head around chaining together promises to achieve a desired result.

Brief background: I'm Using Ionic2 (based on Angular2) to create mobile app. Data persistence is based on SQLite. In order to re-build a complex object that contains nested arrays, I need to chain together a number of database calls.

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});
        }
      }
    );
  }

This method aims to fetch a main object from the database, and using it's ID, fetches and appends its related properties from additional tables. I wish to rebuild the object in it's entirety before passing the result back.

However, at the moment, the object is passed back and then over time the properties are added once each additional call is completed.

I would really appreciate if someone could inform me how I can chain these together, so that the controller calling 'buildObjectFromID' gets a complete object.

Many thanks.


回答1:


Two changes you can make:

  1. Remember that then returns a new promise. Since you already have a promise from db.getEventWithCMSID, you don't need to use new Promise at all, just use the one you get from calling then on that one. In general, before reaching for new Promise, consider whether you already have one the work with.

  2. To wait for all of your subordinate operations to complete, use Promise.all.

So:

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 (for brevity I left out two of the subordinate calls, just include banner and images)

That also has the advantage of propagating failures, which your original code didn't do (consider what happens if getBannerForOwner fails, for instance).

Live Example on Babel's REPL demonstrating failure




回答2:


I would leverage the Promise.all method and chain different promises like this:

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;
  });
}


来源:https://stackoverflow.com/questions/37072571/returning-objects-created-by-chained-javascript-promises

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!