正如評論所說,一個承諾的狀態可能只會被改變一次,從掛起到被履行或被拒絕。一旦履行承諾,拒絕將被忽略。
此外,它被認爲是更好的形式來不使用Promise.defer()
,轉而使用new Promise
構造:
return new Promise(function(resolve, reject) {
sendToSocket({...}); // call resolve() here
setTimeout(function() { reject(new Error("timeout")); }, 10000)
});
你會發現,這裏沒有try/catch
,那是因爲無極構造函數中,任何拋出異常會自動轉換爲拒絕。
另一個件事我會做的,是分開的超時的方法,像這樣:
function withTimeout(delay, fn) {
return function() {
return Promise.race([ // race between...
// Promise that rejects after "delay" ms
new Promise(function(resolve, reject) {
setTimeout(function() { reject(new Error("timeout")); }, delay);
}), // and...
// Promise that actually does the action
// The call to `Promise.resolve()` is to ensure we get a Promise
// even if the function doesn't return one.
Promise.resolve(fn.apply(null, arguments))
]);
};
}
this.send = function() {
return new Promise(function(resolve, reject) {
sendToSocket({...}); // call resolve here, or reject on error.
// thrown errors will be converted anyway
});
};
this.sendWithTimeout = withTimeout(10000, this.send.bind(this));
調用withTimeout
將返回一個新功能,返回一個承諾與超時選項。
Promise.race()
返回一個Promise,該Promise解析(或拒絕)當Promise中的第一個Promise超出Promises數組解決或拒絕的情況。我們比賽之間的實際承諾返回從this.send()
和一個承諾,將在超時拒絕。
這意味着您的this.send()
函數只處理實際發送。超時是您通過抽象添加的細節。
一個Promise只能解析一次(在這種情況下,我使用resolve這個詞來表示成功履行或拒絕錯誤)......一旦解決,任何拒絕或履行的企圖都會被忽略 - 因此,超時**將始終運行到完成**,但如果Promise已經完成,拒絕將不會影響Promise - 閱讀spec中的2.1節 - https://promisesaplus.com/ –
@JaromandaX如果我添加了一些如果sendToSocket在10秒之前成功通過,那麼'setTimeout'內部的'def.reject'會在它之前運行'log'打印,如果不是的話 - 我認爲這是什麼原因導致它無法運行? – Jas
'如果我在setTimeout'內部的def.reject之前添加一些日誌打印 - 做到這一點,看看 - 它應該記錄 –