简体   繁体   中英

How to (elegantly) interrupt Promises chain execution with Q

I have a chain of promises that looks like this:

module.exports.deleteCommunityFollower = function deleteCommunityFollower(req, res){
  var communityId = req.params.userId;
  var followerId = req.session.passport.user.userId;

  var community = new user_model.User(communityId);
  community.getFollower(followerId)
    .then(function(data) {
      if(data.length === 0) {
        res.sendStatus(404); //no follower found, interrupt execution
      } else {
       return community.removeFollower(data[0]); //returns a promise
      }      
    })
    .then(function() {
      res.sendStatus(201); //follower removed, success
    })
    .fail(function(error) {
      errorHelper.diagnosticsUploader(error, community);
      res.sendStatus(500);      
    });
}

My question here is about line res.sendStatus(404) . Is this a correct and elegant way of interrupting execution of a chain of promises? The background is, sometimes when chaining promises, I've found scenarios like this one, where you need to stop the execution of the chain for reasons that are not an error . I know I could throw an artificial error upon data.length === 0 , but that just looks inelegant to me.

In the code above, when data.length === 0 is true, I simply return an http response and do not return any value to the promise resolver, thus effectively preventing the chain execution to continue. However, I'd like to validate if this is recommended practice. Leaving a promise hanging mid-way looks to me like it can be a source of trouble in the future (memory leaks?)

Since you are using modern node, here is how I would write it using Q.async :

const deleteFollower = Q.async(function*(communityId, followerId){ 
    const community = new user_model.User(communityId);
    let followers = yield community.getFollower(followerId);
    if(followers.length) === 0; return false;
    yield community.removeFollower(follower[0]);
    return true;
});

Reads like a synchronous function and completely flat, nice huh?

I omitted the code extracting things from req/res since that would make the code harder to test and it should probably be separated anyway. I'd call it like:

function handler(req, res){
    var communityId = req.params.userId;
    var followerId = req.session.passport.user.userId;
    deleteFollower(communityId, followerId).then(val => {
        if(val) res.sendStatus(201);
        else res.sendStatus(404);
    }).fail(err => {
        res.sendStatus(500);
        errorHelper.diagnosticsUploader(err); 
    });
}

(Note, personally I much prefer using the bluebird library for performance reasons, where I'd use Promise.coroutine ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM