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

将其他信息传递给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布尔值,或者实现另一种优雅的方式来区分接收到的错误?

+0

我真的不明白它。该布尔似乎总是“真实的”。你究竟想知道哪里不对? – Bergi

+0

[我如何访问以前的承诺会导致.then()链]?(http://*.com/q/28250680/1048572),但我会尝试给出具体的答案 – Bergi

+0

例如,如果第一个getAsync调用返回错误,它会将它传递给处理程序,并且在那个时候,如果有条件地检查处理程序中的postingSuccessfully的值,处理程序可以知道在delAsync调用之前收到此错误被制造了。但是,如果处理程序可以检查postingSuccessfully的值并确定它是真的,它就知道该帖子成功完成,并可以告诉我该权限用于发布帖子。让我知道这是否合理。 – Antoine

也许我真的不明白你想做什么,但发电机功能的好处之一是,你可以使用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(){}); 
    … 
+0

非常感谢这真棒的代码。 :)工具箱中有许多不同的工具供我玩,我从来没有在发生器中尝试过try-catch语句!感谢无限! – Antoine

+0

@mrmayfield:是的确:-)然而(也许你看过我不断编辑答案),有很多陷阱。我不会推荐在你想分别处理成功和异常情况的情况下使用'try-catch' - JS缺少某种'try-catch-else' :-) – Bergi

+0

是的,我玩过try捕捉流量并让它工作,但我最终可能会使用最终承诺的(成功,失败)模式。今天早上我也开始使用生成器,这要感谢你提到的'如何访问.then()链中的先前承诺结果?'答案,所以我今天肯定来了你的帮助全方位哈哈。 :) – Antoine

很多方法可以做到这一点。也许最简单的办法就是让你的postId进入了保存状态的对象:

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

...然后你就可以,只要你喜欢,以测试它。另一种(更复杂的)方式是分成多个承诺,但我不确定如果不理解现有功能,我可能会对代码产生刺戳。

+0

是的,我打算这么做,但问题是这个例子中的代码会在我返回postId的值之前爆炸,错误处理函数将无法检查examplePost对象的值。 – Antoine

+0

你可以为传入的对象吗?那总是存在的,对吧? –

+0

我会尽力。我正在尝试的一件事是在我的代码的顶部声明为一个空字符串,然后尝试在我的代码内部将其值更改为true,但我无法更改外部作用域中的变量值。我发誓我应该可以使用.apply方法手动将内部作用域的上下文更改为外部作用域,但是我无法将自己的手指放在Node中哈哈。但我会在此期间尝试您的答案,我认为这可能是可能的,或者我可能遇到同样的错误,我无法更改在外部范围中声明的变量。 – Antoine