What is the below express router doing

31 views
Skip to first unread message

Rohan Pota

unread,
Sep 6, 2017, 10:15:19 AM9/6/17
to nodejs
The tutorial that I am follwin has the following 2 router methods for getting the articles from db.

    router.param('article', function(req, res, next, slug) {
      Article.findOne({ slug: slug})
        .populate('author')
        .then(function (article) {
          if (!article) { return res.sendStatus(404); }
    
          req.article = article;
    
          return next();
        }).catch(next);
    });

    router.get('/:article', auth.optional, function(req, res, next) {
      Promise.all([
        req.payload ? User.findById(req.payload.id) : null,
        req.article.populate('author').execPopulate()
      ]).then(function(results){
        var user = results[0];
    
        return res.json({article: req.article.toJSONFor(user)});
      }).catch(next);
    });

I have two questions regarding the methods above,

 1. How does `Promise.all()` work ?
 2. Why do we need to repopulate author field in `router.get()` method when already did that in the `router.param()` method?

vito

unread,
Sep 7, 2017, 3:09:04 AM9/7/17
to nodejs
1. The Promise.all() method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.[1]

so it will return a promise when User.findById and execPopulate promise is resolve 

2. From the look of it, you shouldn't need to repopulate the author, take it out see if still works as inteneded :-)

Zlatko

unread,
Sep 7, 2017, 3:19:15 AM9/7/17
to nodejs
Hi,


On Wednesday, September 6, 2017 at 4:15:19 PM UTC+2, Rohan Pota wrote:

 1. How does `Promise.all()` work ?

Promise.all works like this: you give it an array of promises, and it returns a single promise that is resolved when all the initial promises are done.
Meaning, in a case like this:

    Promise.all([p1, p2, p3, ..., pn])
      .then(handlerFuinction)
      .catch(errorHandlerFunction);

In the example above, you give a handler (callback), but it won't get called until ALL of the p1, p2, p3.. are resolved.
If any of the promises fails or throws, your entire chain will get canceled. Now be careful here, some of the promises may have been resolved already (e.g. updated stuff in db), while others are still in progress, so you might have to do some cleanup call in the .catch handler.

In your case, you first have a promise to be something of this:

    req.payload ? User.findById(req.payload.id) : null,

So if a call to this endpoint was authenticated (I assume that's wath auth.optional does), we get a User.findById(), otherwise we just get null (without going to db).
So in any case, your first promise will either return a user object or it will return null.

Your second promise is that execPopulate() promise.

Now, when both of these are done (both getting the user and populating that article), your last handler gets called. But if any of those fails (e.g. the database is down or the network breaks or whatever)

 
 2. Why do we need to repopulate author field in `router.get()` method when already did that in the `router.param()` method?

Well, I can't tell easily without looking in the code, but it looks like you can take out the second call to populate. That'd be the second promise in your Promise.all array. You could also skip the router.param up there completely, but you may be using that somewhere later on the router, so make sure it all works without it if you go that route (no pun intended :)).

 

Reply all
Reply to author
Forward
0 new messages