如何在Promise中间返回对客户的响应?

时间:2016-03-17 06:54:33

标签: node.js promise bluebird

例如,

Comments.findOne({user: req.user.id}).exce()
.then(function(comment) {
  if(comment) {
    // how to make this return immediately and break the rest then?
    return res.json({error: 'Already commented'});
  } else {
    return Posts.findOne({postId: req.params.id}).exec();
  }
})
.then(function(post) {
  if(post) {
    var comment = new Comment({user: req.user.id, data: req.body.comment})
    return {post: post, comment: comment.save()};
  } else {
    return res.json({error: 'Post not exist'});
  }
})
.then(function(data) {
  post.comments.push(comment._id);
  return post.save();
});
.then(function(post) {
  return res.json({ok: 1})
})
.catch(function(e)) {
  return res.json(error: e);
});

这个承诺是否正确? 怎么写这种承诺? 回调/承诺令人头疼......

2 个答案:

答案 0 :(得分:3)

你正在使用蓝鸟,它支持cancellation。这是一个例子:

var Promise = require('bluebird');
// enable cancellation
Promise.config({
    cancellation: true
});

// store your promise chain
var myPromise = Promise.resolve().then(() => {
    return 'foo';
}).then((res) => {
    console.log(res);
    // call cancel on the chain when needed
    myPromise.cancel();
    return res;
}).then((res) => {
    // this will not be executed
    console.log(res + '2');
});

答案 1 :(得分:2)

您只需要throw或返回拒绝承诺以触发promises中的错误处理,如下例所示:

Comments.findOne({user: req.user.id}).exce()
.then(function(comment) {
  if(comment) {
    // to bypass all the other .then() resolve handlers, either
    // throw an error here or return a rejected promise
    throw new Error(res.json({error: 'Already commented'}));
  } else {
    return Posts.findOne({postId: req.params.id}).exec();
  }
})

Promise是“throw safe”,这意味着.then()将捕获抛出的任何异常并将其转换为被拒绝的promise。这将绕过任何后续.then()解析处理程序,而是转到下一个reject处理程序或.catch()处理程序。

仅供参考,你应该小心你的代码,因为当你.catch()然后从那里返回时,它会将你的承诺状态从拒绝改为已解决,然后当你真正有一个成功的承诺时它会看起来像一个成功的承诺错误,任何来电者都认为一切都很成功。这是因为promise基础结构假定如果您.catch()出现错误并返回一个已“处理”错误的值,则状态现在已成功解决。要允许错误继续从.catch()传播到更高的调用者,您必须重新抛出或返回被拒绝的承诺:

blah(...).then(...)
.catch(function(e)) {
     throw new Error(res.json(error: e));
});