1

Consider this piece of code:

WordPress.getMediaById(res.data.featured_media)
.then(function (res) {
  post.featuredMedia = res.data.source_url;

  WordPress.getUserById(post.authorId)
    .then(function (res) {
      post.authorName = res.data.name;

      $scope.post = {
        title: post.title,
        introAsHtml: post.introAsHtml,
        authorName: post.authorName,
        contentAsHtml: post.contentAsHtml,
        featured_media: post.featuredMedia
      };
    });
});

Is there any way to make it more efficient in terms of nesting? In the future I will want to add more promised functions into it and I am not sure if it's the right way, otherwise, how does it really differ from callbacks...

Regards.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Ariel Weinberger
  • 2,195
  • 4
  • 23
  • 49

2 Answers2

4

You can reduce the nesting like this:

WordPress.getMediaById(res.data.featured_media)
.then(function (res) {
    //res.data is media
  post.featuredMedia = res.data.source_url;

  return WordPress.getUserById(post.authorId);
}).then(function (res) {
    //res.data is user
  post.authorName = res.data.name;

  $scope.post = {
    title: post.title,
    introAsHtml: post.introAsHtml,
    authorName: post.authorName,
    contentAsHtml: post.contentAsHtml,
    featured_media: post.featuredMedia
  };
});

For more info and a clear explanation of promises, read this blog by Nolan Lawson

fikkatra
  • 5,605
  • 4
  • 40
  • 66
  • Your link is broken. – Bergi Apr 12 '16 at 09:11
  • So if I return an execution of another function that returns a promise, I can immediately chain them with ".then"? Have I understood correctly? – Ariel Weinberger Apr 12 '16 at 09:19
  • @Ariel: You can shorten that to "If I return a promise from the `then` callback, …", but in general [yes](http://stackoverflow.com/a/22562045/1048572) – Bergi Apr 12 '16 at 09:20
4

Unless the second async request does not depend on the result of the first call I definitely would not nest the promises.

With the help of angular's $q, you can so this:

$q.all([
  WordPress.getMediaById(mediaId),
  WordPress.getUserById(userId)])
.then(response => {
  post.featuredMedia = response[0].data.source_url;
  post.authorName = response[1].data.name;
  $scope.post = {
    title: post.title,
    introAsHtml: post.introAsHtml,
    authorName: post.authorName,
    contentAsHtml: post.contentAsHtml,
    featured_media: post.featuredMedia
  };
});
webduvet
  • 4,220
  • 2
  • 28
  • 39
  • OP tagged his question with Q, so you shouldn't use `$q` instead. – Bergi Apr 12 '16 at 09:16
  • @Bergi you are right. but it's tagged with angular at first place and hence since he/she did not explicitly mentioned only using Q it is still a valid answer. Not to mention that Q has an equivalent solution. – webduvet Apr 12 '16 at 09:22
  • I am actually using angular's $q. Thank you @webduvet. I also added angular and Ionic so I thought it's obvious. – Ariel Weinberger Apr 12 '16 at 09:30
  • @webduvet so cool solution, you can even use objects with keys instead of arrays. Changed this to the answer!!! Thanks! – Ariel Weinberger Apr 12 '16 at 09:36