2015-04-14 58 views
4

我有一個包含超時承諾的服務器請求。如何查看WinJS.Promise是否被超時取消或取消()調用

var pendingRequest = WinJS.Promise.timeout(5000, requestAsync)

用戶還在UI上有一個「取消」按鈕,通過執行pendingRequest.cancel()來主動取消該請求。但是,沒有辦法發現承諾已被用戶取消或超時(因爲超時在內部也會調用promise.cancel())。

這本來很不錯的WinJS.Promise.timeout會將錯誤狀態中的承諾移動到不同的Error對象,如「超時」而不是「已取消」。

任何想法如何找出請求是否被超時取消?

更新:這個怎麼樣的解決方案:

(function (P) { 
     var oldTimeout = P.timeout 
     P.timeout = function (t, promise) { 
      var timeoutPromise = oldTimeout(t); 
      if (promise) { 
       return new WinJS.Promise(function (c, e, p) { 
        promise.then(c,e,p); 
        timeoutPromise.then(function() { 
         e(new WinJS.ErrorFromName("Timeout", "Timeout reached after " + t + "ms")); 
        }); 
       }); 
      } else { 
       return timeoutPromise; 
      } 
     }; 
    })(WinJS.Promise); 

回答

1

the documentation

...承諾進入錯誤狀態,錯誤的值( 「取消」)

因此,error.message === 'Canceled'可以在您的錯誤處理程序中檢測到。

另外,WinJS.Promise允許在施工時指定onCancel回調。

var promise = new WinJS.Promise(init, onCancel); 

其中initonCancel是兩種功能。

Here's a demo

編輯

OK啊,對不起,我誤解了問題。我現在明白你希望區分超時和手動取消的承諾。

是的,這是可以做到,通過進行適當的信息提供給兩個:

  • 一個WinJS承諾的onCancel回調
  • 鏈式「捕獲」的回調。

首先,使用.timeout()方法延伸WinJS.Promise.prototype:

(function(P) { 
    P.prototype.timeout = function (t) { 
     var promise = this; 
     promise.message = 'Canceled'; 
     P.timeout(t).then(function() { 
      promise.message = 'Timeout'; 
      promise.cancel(); 
     }); 
     return promise.then(null, function() { 
      if(error.message == 'Canceled') { 
       throw new Error(promise.message); //This allows a chained "catch" to see "Canceled" or "Timeout" as its e.message. 
      } else { 
       throw error; //This allows a chained "catch" to see a naturally occurring message as its e.message. 
      } 
     }); 
    }; 
})(WinJS.Promise); 

這變得WinJS.Promise()的每個實例的方法,因此不與靜態衝突方法WinJS.Promise.timeout()

現在,使用.timeout()方法如下:

function init() { 
    //whatever ... 
} 

function onCancel() { 
    console.log('onCacnel handler: ' + this.message || `Canceled`); 
} 

var promise = new WinJS.Promise(init, onCancel); 

promise.timeout(3000).then(null, function(error) { 
    console.log('chained catch handler: ' + error.message); 
}); 

promise.cancel(); 
/* 
* With `promise.cancel()` uncommented, `this.message` and `error.message` will be "Canceled". 
* With `promise.cancel()` commented out, `this.message` and `error.message` will be "Timeout". 
*/ 

Demo(有用於按鈕的動畫附加代碼)。

+1

我知道。那就是問題所在。無論是否由於timeout超時而取消承諾,或者通過超時承諾的其他人致電取消,都是不可能知道的。 – philk

+0

@philk只是...自己推出'.timeout'? –

+0

編輯答案。我認爲它現在回答了這個問題。 –