将其他信息传递给Promises错误处理程序
我已经promisified fbgraph nodeJS API并使用它来测试功能。此功能发布到给定的Facebook群组,然后验证帖子是否已正确通过并删除帖子。此代码的目的是测试用户是否拥有针对不同组的阵列的权限。将其他信息传递给Promises错误处理程序
目前使用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布尔值,或者实现另一种优雅的方式来区分接收到的错误?
也许我真的不明白你想做什么,但发电机功能的好处之一是,你可以使用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 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语句!感谢无限! – Antoine
@mrmayfield:是的确:-)然而(也许你看过我不断编辑答案),有很多陷阱。我不会推荐在你想分别处理成功和异常情况的情况下使用'try-catch' - JS缺少某种'try-catch-else' :-) – Bergi
是的,我玩过try捕捉流量并让它工作,但我最终可能会使用最终承诺的(成功,失败)模式。今天早上我也开始使用生成器,这要感谢你提到的'如何访问.then()链中的先前承诺结果?'答案,所以我今天肯定来了你的帮助全方位哈哈。 :) – Antoine
很多方法可以做到这一点。也许最简单的办法就是让你的postId
进入了保存状态的对象:
var examplePost = {
id: 14715395189,
postedSuccessfully: false
};
...然后你就可以,只要你喜欢,以测试它。另一种(更复杂的)方式是分成多个承诺,但我不确定如果不理解现有功能,我可能会对代码产生刺戳。
是的,我打算这么做,但问题是这个例子中的代码会在我返回postId的值之前爆炸,错误处理函数将无法检查examplePost对象的值。 – Antoine
你可以为传入的对象吗?那总是存在的,对吧? –
我会尽力。我正在尝试的一件事是在我的代码的顶部声明为一个空字符串,然后尝试在我的代码内部将其值更改为true,但我无法更改外部作用域中的变量值。我发誓我应该可以使用.apply方法手动将内部作用域的上下文更改为外部作用域,但是我无法将自己的手指放在Node中哈哈。但我会在此期间尝试您的答案,我认为这可能是可能的,或者我可能遇到同样的错误,我无法更改在外部范围中声明的变量。 – Antoine
我真的不明白它。该布尔似乎总是“真实的”。你究竟想知道哪里不对? – Bergi
[我如何访问以前的承诺会导致.then()链]?(http://*.com/q/28250680/1048572),但我会尝试给出具体的答案 – Bergi
例如,如果第一个getAsync调用返回错误,它会将它传递给处理程序,并且在那个时候,如果有条件地检查处理程序中的postingSuccessfully的值,处理程序可以知道在delAsync调用之前收到此错误被制造了。但是,如果处理程序可以检查postingSuccessfully的值并确定它是真的,它就知道该帖子成功完成,并可以告诉我该权限用于发布帖子。让我知道这是否合理。 – Antoine