将其他信息传递给Promises错误处理程序

时间:2015-06-21 21:20:05

标签: javascript node.js promise generator bluebird

我已经宣传了fbgraph nodeJS API并且正在使用它来测试一个功能。此功能发布到给定的Facebook群组,然后验证帖子已正确完成并删除帖子。此代码的目的是测试用户是否具有不同组的发布权限。

目前使用Bluebird的Promise库和生成器实现的代码。

var examplePostId = 12345678910

facebookPoster = Promise.coroutine(function* (feedId) {

  var postResponse = yield graph.postAsync(feedId + '/feed', sampleData);
  var postId = postResponse.id
  var getResponse = yield graph.getAsync(postId)
  var returnedId = getResponse.id
  var postedSuccessfully = true // <-- This is what I want to reference in my error handler.
  var deleteResponse = yield graph.delAsync(postId)
  var getAfterDeleteResponse = yield graph.getAsync(postId) // I expect this to throw an error since the post should already be deleted
  return postId

})

facebookPoster(examplePostId).then(function(postId){
  console.log(postId);
}).catch(function(err){
  console.log(err); // How can I tell the handler that error is fine because postedSuccessfully is true?
})

这就是我的麻烦:FB的图谱API非常不可靠。即使帖子实际上没有被删除,我仍然会收到成功的回复(记录在这里:___)。

因此,在我的生成器中,我试图第二次获取postID的信息,并期待它爆炸。当我收到错误时,它会传递给我的处理程序并触发我的处理程序。这很好,但我希望能够引用postedSuccessfully布尔值来区分我期望收到的错误和意外的错误。

如何引用postedSuccessfully布尔值,或者实现另一种优雅方式来区分收到的错误?

2 个答案:

答案 0 :(得分:1)

有很多方法可以做到这一点。可能最简单的方法是将postId变成一个保持状态的对象:

var examplePost = {
    id: 14715395189,
    postedSuccessfully: false
};

...然后你可以随时测试它。另一种(更复杂的)方法是分解多个承诺,但我不确定如果不更好地理解现有功能,我可能会对代码进行攻击。

答案 1 :(得分:1)

也许我真的不明白你想做什么,但是生成器函数的一个好处就是你可以使用try - catch - 语句来熟悉它们

因此,您可以使用

执行文本中描述的操作
var facebookPoster = Promise.coroutine(function* (feedId) {
  try {
    var postId = (yield graph.postAsync(feedId + '/feed', sampleData)).id;
    var returnedId = (yield graph.getAsync(postId)).id;
    var postedSuccessfully = true;
    var deleteResponse = yield graph.delAsync(postId);
    var getAfterDeleteResponse = yield graph.getAsync(postId);
  } catch (e) {
    if (!postedSuccessfully) // ignore error, it's expected
      throw e;
  }
  return postId;
});

facebookPoster(12345678910).then(console.log.bind(console), console.error.bind(console));

但是我认为以下更清洁:

var facebookPoster = Promise.coroutine(function* (feedId) {
  var postId = (yield graph.postAsync(feedId + '/feed', sampleData)).id;
  var returnedId = (yield graph.getAsync(postId)).id;
  var deleteResponse = yield graph.delAsync(postId);
  try { // sometimes deleteResponse is wrong, so double-check
    var getAfterDeleteResponse = yield graph.getAsync(postId);
  } catch (e) {
    // ignore error, it's expected
  } finally {
    if (getAfterDeleteResponse)
      throw new Error("hey it's still there while it shouldn't be!");
  }
  console.log(postId);
});

facebookPoster(12345678910).catch(console.error.bind(console));

甚至更好,通过使用then(success, fail) pattern来避免那种可怕的尝试捕捉终极事物:

  …
  // sometimes deleteResponse is wrong, so double-check
  var getAfterDeleteResponse = yield graph.getAsync(postId).then(function(post) {
    throw new Error("hey it's still there while it shouldn't be!");
  }, function ignoreExpectedError(){});
  …