2015-06-21 96 views
0

我已經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://stackoverflow.com/q/28250680/1048572),但我會嘗試給出具體的答案 – Bergi

+0

例如,如果第一個getAsync調用返回錯誤,它會將它傳遞給處理程序,並且在那個時候,如果有條件地檢查處理程序中的postingSuccessfully的值,處理程序可以知道在delAsync調用之前收到此錯誤被製造了。但是,如果處理程序可以檢查postingSuccessfully的值並確定它是真的,它就知道該帖子成功完成,並可以告訴我該權限用於發佈帖子。讓我知道這是否合理。 – Antoine

回答

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 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

1

很多方法可以做到這一點。也許最簡單的辦法就是讓你的postId進入了保存狀態的對象:

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

...然後你就可以,只要你喜歡,以測試它。另一種(更復雜的)方式是分成多個承諾,但我不確定如果不理解現有功能,我可能會對代碼產生刺戳。

+0

是的,我打算這麼做,但問題是這個例子中的代碼會在我返回postId的值之前爆炸,錯誤處理函數將無法檢查examplePost對象的值。 – Antoine

+0

你可以爲傳入的對象嗎?那總是存在的,對吧? –

+0

我會盡力。我正在嘗試的一件事是在我的代碼的頂部聲明爲一個空字符串,然後嘗試在我的代碼內部將其值更改爲true,但我無法更改外部作用域中的變量值。我發誓我應該可以使用.apply方法手動將內部作用域的上下文更改爲外部作用域,但是我無法將自己的手指放在Node中哈哈。但我會在此期間嘗試您的答案,我認爲這可能是可能的,或者我可能遇到同樣的錯誤,我無法更改在外部範圍中聲明的變量。 – Antoine