【问题标题】:Passing additional information to Promises error handler将附加信息传递给 Promises 错误处理程序
【发布时间】:2015-06-21 21:20:04
【问题描述】:

我已承诺 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 的 Graph API 非常不可靠。即使帖子实际上没有被删除,我仍然会收到成功响应(记录在此处:___)。

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

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

【问题讨论】:

  • 我不太明白。该布尔值似乎总是true。您究竟想在不真实的地方捕捉到什么?
  • How do I access previous promise results in a .then() chain? 可能重复,但我会尝试给出具体答案
  • 例如,如果第一个 getAsync 调用返回错误,它将把它传递给处理程序,此时,如果我有条件地在处理程序中检查 postedSuccessfully 的值,处理程序可以知道在进行 delAsync 调用之前收到此错误。但是,如果处理程序可以检查 postedSuccessfully 的值并看到它是真的,它就知道帖子已成功通过,并可以告诉我有发布帖子的权限。让我知道这是否有意义。
  • 顺便说一句,我很抱歉,但我已经删除了第二个接听电话!我现在已经将它添加到代码中,希望它现在更有意义,我的错!
  • 啊,是的,现在我认为我的回答也有道理:-)

标签: javascript node.js promise generator bluebird


【解决方案1】:

也许我并没有真正理解你想要做什么,但是生成器函数的好处之一是你可以像以前一样在其中使用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(){});
  …

【讨论】:

  • 非常感谢这个非常棒的代码。 :) 工具箱中有很多不同的工具供我使用,而且我之前从未在生成器中尝试过 try-catch 语句!无限感谢!
  • @mrmayfield:确实是 :-) 但是(也许你已经看到我不断地编辑答案)有很多陷阱。对于要分别处理成功和异常情况的情况,我不建议使用try-catch - JS 缺少某种try - catch - else :-)
  • 是的,我玩过 try catch 流程并让它工作,但我最终可能会使用最终承诺的 then(success,fail) 模式。我今天早上也开始使用生成器,这要归功于您前面提到的“如何在 .then() 链中访问以前的承诺结果?”答案,所以我今天肯定会在你的帮助下绕圈子哈哈哈。 :)
【解决方案2】:

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

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

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

【讨论】:

  • 是的,我正打算这样做,但问题是,在我返回 postId 的值之前,此示例中的代码会崩溃,并且错误处理函数将无法返回检查 examplePost 对象的值。
  • 可以为传入的对象做吗?那总是存在的,对吧?
  • 我一定会尝试的。我正在尝试的一件事是在我的代码顶部将postedSuccesfully声明为一个空字符串,然后尝试在我的代码内部将其值更改为true,但我无法在外部范围内更改变量的值。我发誓我应该能够使用 .apply 方法手动将内部作用域的上下文更改为外部作用域的上下文,但我无法准确指出 Node 中的具体方式哈哈。但我会同时尝试你的答案,我认为这可能是可能的,或者我可能会遇到同样的错误,我无法更改在外部范围中声明的变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2015-12-30
相关资源
最近更新 更多