2013-08-01 33 views
1

我基本上需要的是在實際創建之前公開一個Deferred。例如,假設我有一些對象,它是包裝一個Ajax查詢,但它開始之前,它需要揭露遞延,表示查詢的分辨率:包裝jQuery的模式推遲到另一個延期?

var object = new AjaxRunningThing(); 
// Get a Deferred wrapping the Ajax operation 
var ajaxResult = object.getAjaxResult(); 

// Later... 

// Now the object is going to initiate the Ajax request 
object.startAjax(); 

現在我只是手動鏈接起來,使的「真正的」遞延分辨率鏈接到「門面」之一:

// in getAjaxResult() 
var publicDeferred = $.Deferred(); 

// in startAjax() 
var privateDeferred = $.ajax(...); 
privateDeferred.then(
    function() { publicDeferred.resolve.apply(this, arguments); }, 
    function() { publicDeferred.reject.apply(this, arguments); } 
); 

我不能不認爲有更好的方式來做到這一點,雖然。

- 編輯---

有關它的更多,我要找的是一個真正的代理思考 - 搜索「代理」使我這個職位,其中描述了我在尋找並且包括一個更好的(雖然還沒有完全透明)的解決方案:Propagating events between JQuery.Deferred objects

+2

我不明白這一點,如果AJAX調用返回延期對象,在同一時間用相同的參數解決? – adeneo

+0

因爲在發生ajax調用之前,有一些其他組件會要求它 - 這裏的延遲是「將在無限期內發生的一些Ajax調用」 – Adam

+0

您的解決方案很好 - Q promise中有更多巧妙的解決方案,但jQuery的承諾是_really_光禿禿的骨頭和基本的。 –

回答

0

級聯解決的承諾是相當瑣碎。我們經常看到這一點,很多時候單一的承諾就足夠了。您在這裏需要的可以被稱爲「延遲法律模式」(與「延遲反模式」相反)。

對我來說,這是更多的代碼是如何不是簡單的編碼級聯因素。

這裏是一個可能的辦法:

function getLatentAjaxPromise(options) { 
    var dfrd = $.Deferred(), 
     promise = dfrd.promise(), 
     jqXHR; 

    // monkeypatch the promise with a `go()` method. 
    promise.go = function(opts) { 
     if(!jqXHR) { // in case .go() is called more than once. 
      jqXHR = $.ajax($.extend(options, opts)).then(dfrd.resolve, dfrd.reject); 
     } 
     return promise; 
    }; 
    return promise; 
}; 

這將使:

  • 遞延對象本身要保密,
  • AJAX選項要傳遞給getLatentAjaxPromise和/或.go
  • 承諾鏈要建到getLatentAjaxPromise()和/或.go()

電話如下:

var latentAjaxPromise = getLatentAjaxPromise(...).then(...); 

//and later ... 
latentAjaxPromise.go(...).then(...); 

應該不會出現雙承諾鏈的任何不良後果,但你也許需要保持你的智慧。從消費者的角度來看,兩條連鎖店都來自相同的承諾並不明顯。

我會很感興趣的,看看有沒有人可以在邏輯中發現任何明顯的缺陷。

0

只是爲了關閉,這裏是我解決的解決方案。它使用作品從這裏其他的答案,但是這是我所需要的功能:爲什麼你會需要包裝,在另一遞延

// Private deferred that will be resolved when the Ajax is complete 
var _done = $.Deferred(); 
// Expose the deferred as a promise, so it's read-only to other components 
var done = _done.promise(); 

// ... other components add their own callbacks to `done` 

// Later, run the ajax, and resolve the deferred based on that 
$.ajax(...).then(
    _done.resolve, _done.reject, _done.notify);