2016-09-21 69 views
0

如果sendToSocket成功,爲什麼setTimeoutdef.reject代碼不能運行?如果sendToSocket成功,爲什麼setTimeout def.reject代碼不能運行?

this.send = function(type, body) { 
    var def = Promise.defer(); 
    try{ 
     sendToSocket({...}); 
     setTimeout(function() { // if the send sendToSocket Succeeds how does nodejs/javascript know not to run the timeout code after 10 seconds? 
      def.reject(new Error("timeout")); 
     }, 10000); 
    }catch(err){ 
     logger.error('error'); 
     def.reject(err); 
    } 

    return def.promise; 
}; 
+2

一個Promise只能解析一次(在這種情況下,我使用resolve這個詞來表示成功履行或拒絕錯誤)......一旦解決,任何拒絕或履行的企圖都會被忽略 - 因此,超時**將始終運行到完成**,但如果Promise已經完成,拒絕將不會影響Promise - 閱讀spec中的2.1節 - https://promisesaplus.com/ –

+0

@JaromandaX如果我添加了一些如果sendToSocket在10秒之前成功通過,那麼'setTimeout'內部的'def.reject'會在它之前運行'log'打印,如果不是的話 - 我認爲這是什麼原因導致它無法運行? – Jas

+0

'如果我在setTimeout'內部的def.reject之前添加一些日誌打印 - 做到這一點,看看 - 它應該記錄 –

回答

2

正如評論所說,一個承諾的狀態可能只會被改變一次,從掛起到被履行或被拒絕。一旦履行承諾,拒絕將被忽略。

此外,它被認爲是更好的形式來使用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()函數只處理實際發送。超時是您通過抽象添加的細節。

+0

好!不知道'.race'! – Jas

相關問題