2014-01-29 26 views
1

tl; dr:我正在尋找一種方法,讓第一個.then回調對傳遞給後續鏈接事件的數據進行更改。jQuery承諾中的突變參數

我有一個封裝了一些異步操作的庫。

dudetools.getDude(2); // causes an XHR against REST resource "Dude" for row id 2 

,迷死人的目的,dudetools.getDude返回由底層$.ajax調用創建的承諾。因此,我可以做這樣的事情:

dudetools.getDude(dudeId).done(function(dudeData) { /* do stuff with dude's data */ }); 

現在我試圖修改dudetools,這樣它會做一些方便的數據按摩沿諾言鏈繼續之前的響應數據。我希望這種按摩能夠普遍發生,而不需要調用代碼來請求它,甚至不需要知道它。

因爲dudetools實現無法與所有調用代碼共享一個閉包,所以我希望利用這樣的事實:在JavaScript中,非標量總是通過引用而不是按值傳遞。

考慮:

var urStuff = {}; 
function wreck(x) { 
    x.isWrecked = 'so wrecked'; 
} 
wreck(urStuff); 
// urStuff.isWrecked === 'so wrecked' ^.^ 

你來試試吧。

所以,我希望這會工作:

dudetools = { 
    'getDude': function(dudeId) { 
     return $.ajax('/api/Dude/' + dudeId).then(function(dudeData) { 
      // I'm so clever! 
      dudeData.isDuplicated = dudeData.isDuped && dudeData.drillDown > 5; 
     }); 
    } 
} 

。當然,這是行不通的。我的巧妙代碼正在執行(我見過它),並且它達到了正確的結論,但鏈中的後續延遲事件從未看到這些修改。 I.e .:

$.when(
    dudetools.getDude(dudeId) 
).done(function(mysteriouslyUnmodifiedInfo) { 
    /* the info passed to this function is mysteriously unmodified! HALP */ 
}); 

有什麼建議嗎?有什麼方法可以完成我所追求的目標?

另外:我對整體承諾還是有點新,而我對延遲,承諾和相關結構之間差異的把握仍然有點模糊,所以我非常感謝你的努力,並在向我解釋我是如何毀掉一切的時候明確表示的。

非常感謝。

編輯:更新,以反映事實dudetools.getDude返回承諾,不會延遲一個。因爲我現在(大部分)都明白不同之處。

回答

0

你會想要返回自己的新的Deferred.promise()對象。 http://api.jquery.com/deferred.promise/

dudetools = { 
    'getDude': function(dudeId) { 
     var dfd = new jQuery.Deferred(); 
     $.ajax('/api/Dude/' + dudeId).then(function(dudeData) { 
      dudeData.isDuplicated = dudeData.isDuped && dudeData.drillDown > 5; 
      // I'm so clever! 
      dfd.resolve(dudeData); 
     }); 

     return dfd.promise(); 
    } 
} 

希望有所幫助。

+0

這可能工作,但簡單地返回自定義'then()'修改後的數據更簡單。不管怎麼說,還是要謝謝你。 8) – Tom

+1

哈!最後,這實際上是正確的解決方案。在編寫單元測試時,我發現兩種方法的行爲之間存在不可接受的差異,其中一種使用@ Norguard的方法,其中一種沒有中間人。使用Sumit的方法,變化是完全透明的,我的單元測試再次成功。謝謝! – Tom

+1

不,[不要這樣做](http://stackoverflow.com/q/23803743/1048572)! – Bergi

1

.then的神奇之處在於它的管道返回值爲下一個回調參數。

如果你沒有返回你的對象(即使你沒有改變任何東西),那麼默認情況下會返回undefined

do_something() 
.then(function (json) { return JSON.parse(json); }) 
.then(function (response) { return response.data; }) 
.then(function (data) { data.tweaked = true; return data; });