[英]Chaining Javascript promises
我試圖從MDN文檔中了解Promises。 第一個示例演示了then
和catch
方法:
// We define what to do when the promise is resolved/fulfilled with the then() call,
// and the catch() method defines what to do if the promise is rejected.
p1.then(
// Log the fulfillment value
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Promise fulfilled (<small>Async code terminated</small>)<br/>');
})
.catch(
// Log the rejection reason
function(reason) {
console.log('Handle rejected promise ('+reason+') here.');
});
文檔聲明then
方法返回一個新的promise,所以不要將上面的代碼等同於
var p2 = p1.then(
// Log the fulfillment value
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Promise fulfilled (<small>Async code terminated</small>)<br/>');
});
p2.catch(
// Log the rejection reason
function(reason) {
console.log('Handle rejected promise ('+reason+') here.');
});
?
如果是這樣,那么這是不是意味着只有當從p1.then
返回的p1.then
而不是promise p1
被拒絕時才會調用catch
回調? 我不是必須這樣做的:
p1.then( /* etc. */ );
// and for rejected resolutions
p1.catch( /* etc. */ );
抓住承諾p1
的拒絕而不是將catch
鏈接到then
?
起初,我認為從p1.then
返回的p1.then
與p1
相同,就像jQuery如何處理它的大部分API一樣。 但以下清楚地表明這兩個承諾是不同的。
var p1 = new Promise(function(resolve, reject) {
resolve("Success!");
});
console.log(p1);
// Promise { <state>: "fulfilled", <value>: "Success!" }
var p2 = p1.then(function(value) {
console.log(value);
});
// Success!
console.log(p2);
// Promise { <state>: "fulfilled", <value>: undefined }
另外,我在JSFiddle中玩了三種方法:
p1.then(onFulfilled).catch(onRejected);
p1.then(onFulfilled); p1.catch(onRejected);
p1.then(onFulfilled, onRejected);
這三個都有效。 我能理解后兩者。 我的問題的要點是,為什么第一種方法也有效?
首先,關於承諾相關部分如何運作的一些背景知識:
p1.then(...)
確實返回一個鏈接到前一個的新承諾。 所以, p1.then(...).then(...)
只有在第一個完成后才會執行第二個.then()
處理程序。 並且,如果第一個.then()
處理程序返回一個未實現的promise,那么它將在解析第二個promise並調用第二個.then()
處理程序之前等待該返回的promise解析。
其次,當一個promise鏈拒絕鏈中的任何地方時,它會立即跳過鏈(跳過任何已完成的處理程序),直到它到達第一個拒絕處理程序(無論是來自第二個參數的.catch()
到.then()
)。 這是承諾拒絕的一個非常重要的部分,因為這意味着您不必在承諾鏈的每個級別捕獲拒絕。 您可以在鏈的末尾放置一個.catch()
,並且鏈中任何位置發生的任何拒絕都將直接轉到該.catch()
。
另外,值得理解的是.catch(fn)
只是.catch(fn)
.then(null, fn)
的快捷方式。 它沒有區別。
此外,記住,(就像.then()
一.catch()
也將返回一個新的承諾。 如果你的.catch()
處理程序本身不拋出或返回被拒絕的promise,那么拒絕將被視為“已處理”,並且返回的promise將被解析,允許鏈從那里繼續。 這允許您處理錯誤,然后有意識地決定您是否希望鏈繼續正常的履行邏輯或保持拒絕。
現在,針對您的具體問題......
如果是這樣,那么這是不是意味着只有當從p1.then返回的promise而不是promise p1被拒絕時才會調用catch回調? 我不是必須這樣做的:
拒絕拒絕在鏈中傳播到下一個拒絕處理程序,跳過所有解析處理程序。 因此,它會在您的示例中跳過鏈接到下一個.catch()
。
這是使用錯誤處理錯誤的事情之一。 您可以將.catch()
放在鏈的末尾,它將從鏈中的任何位置捕獲錯誤。
有時候有理由在鏈的中間攔截錯誤(如果你想在錯誤上分支和更改邏輯,然后繼續使用其他代碼),或者如果你想“處理”錯誤並繼續進行。 但是,如果您的鏈是全部或全部,那么您可以在鏈的末尾放置一個.catch()
來捕獲所有錯誤。
它類似於同步代碼中的try / catch塊。 在鏈的末尾放置一個.catch()
就像在一堆同步代碼的最高級別放置一個try / catch塊。 它將捕獲代碼中的任何位置的異常。
這三個都有效。 我能理解后兩者。 我的問題的要點是,為什么第一種方法也有效?
這三個都差不多。 2和3是相同的。 實際上, .catch(fn)
只不過是.catch(fn)
.then(null, fn)
的快捷方式。
選項1略有不同,因為如果onFulfilled
處理程序拋出或返回被拒絕的promise,則會.catch()
處理程序。 在另外兩個選項中,情況並非如此。 除了那一個差異,它將工作相同(如你所觀察到的)。
選項1有效,因為拒絕在鏈中傳播。 因此,如果p1拒絕或者onFulfilled處理程序返回被拒絕的promise或throws,則將.catch()
處理程序。
代碼不應該是等同的
他們是。
如果是這樣,那么這是不是意味着只有當從
p1.then
返回的p1.then
而不是promisep1
被拒絕時才會調用catch回調?
對,就是這樣。
但是當p1
拒絕時, p2
也會這樣做,因為你沒有將onRejected
處理程序傳遞給可以攔截它的onRejected
.then()
調用。 拒絕只是沿着鏈傳播。
我使用這三種方法在JSFiddle中玩游戲。 這三個都有效。
他們這樣做,但他們不這樣做。
p1.then(onFulfilled, onRejected);
這是你通常想做的事情。
p1.then(onFulfilled); p1.catch(onRejected);
最終會有兩個不同的承諾,一個將使用onFulfilled
結果解決或被拒絕,另一個將使用onRejected
結果實現或解決。
p1.then(onFulfilled).catch(onRejected);
那是一個與第一個不同的野獸,看什么時候。然后(成功,失敗)被認為是承諾的反模式? 。
這個:
var p2 = p1.then()
p2.catch()
與此相同:
p1.then().catch()
你也可以這樣做:
p1
.then(response => response.body)
.then(body => JSON.parse(body))
.then(data => console.log(data))
.catch(e => console.log('something somewhere failed'))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.