将附加信息传递给 Promises 错误处理程序

Passing additional information to Promises error handler

我已经承诺 fbgraph nodeJS API 并且正在使用它来测试一个功能。此功能 posts 到给定的 Facebook 群组,然后验证 post 是否已正确通过并删除 post。此代码的目的是测试用户是否具有对不同组数组的 post 权限。

当前使用 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 非常不可靠。即使 post 没有实际删除,我仍然会收到成功响应(记录在此处:___)。

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

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

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

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

...然后你就可以随时测试它了。另一种(更复杂的)方法是分成多个承诺,但我不确定我是否可以在不更好地了解您现有功能的情况下尝试编写代码。

也许我不太明白你想做什么,但是生成器函数的好处之一是你可以在其中使用 try-catch-statements习惯了。

所以您可以使用

来完成您在文本中描述的操作
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:

避免可怕的 try-catch-finally 事情
  …
  // 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(){});
  …