2013-07-30 20 views
1

我有很多的,目前像這樣的功能:鏈接deferreds

function LoadFromURL(url) 
{ 
    var d = $.Deferred(); 
    $.get(url).then(function(text) 
    { 
     LoadFromText(text).then(function(obj) 
     { 
      d.resolve(obj); 
     }, 
     function(err) 
     { 
      d.reject(err); 
     }); 
    }, 
    function(err) 
    { 
     d.reject(err); 
    }); 
    return d.promise(); 
} 

該函數接受一個URL,並加載一個承諾中的文本。該文本然後傳遞給LoadFromText函數,該函數返回另一個承諾。如果成功,則外部延遲已解決。如果URL無法加載,或者LoadFromText函數失敗,則外部延遲被拒絕。

有沒有我可以鏈上的決心/拒絕的結果,像這樣的東西最後一個方法:

function LoadFromURL(url) 
{ 
    return $.get(url).then(function(text) 
    { 
     return LoadFromText(text); 
    }, 
    function(err) 
    { 
     return $.Deferred().reject(err); 
    }).promise(); 
} 

我見過的承諾的一些實現,使這 - 回內的承諾'那麼'意味着使用承諾的最終結果。

我意識到此時此刻不起作用(其結果是諾言,而不是承諾的結果),但希望有人可以提出一種方法來完成這項工作,以便我可以收拾有時令人困惑的混亂第一個例子。

我希望這是有道理的。謝謝。

+0

jQuery的Deferred's'then'方法與我用過的其他許諾庫有點不同。它更多用作過濾器。 (但是,當然,你可以用它來做任何你想要的。)看看'.when()'來代替。如果這不符合你的要求,你的第一個代碼塊看起來就像我會解決這個問題的方式。或者,包括Async.js或其他東西。 – Brad

回答

0

LoadFromURL將簡化如下:

function LoadFromURL(url) { 
    return $.get(url).then(function(text) { 
     return LoadFromText(text); 
    }); 
} 

有可能是你有沒有考慮過的問題...

像你原來的版本,該過程將趨於直到服務器返回一個無限遞歸HTTP錯誤。在適當地編寫服務器資源時,您會遇到輕微的挑戰,特別是在可能的情況下,您需要訪問最終交付的文本。

隨着多一點思考,你可以這樣說,「繼續」或「完成」的文字本身,或在HTTP響應代碼表示提供所有的文本。例如,您可以使用響應代碼202(「已接受」)來表明過程不完整。

我認爲這會工作(使用jQuery 1.5+):

function LoadFromURL(url) { 
    return $.get(url).then(function(text, textStatus, jqXHR) { 
     if(jqXHR.status === 202) {//continue 
      return LoadFromText(text); 
     } 
     else {//complete 
      return text; 
     } 
    }); 
} 

你只需要安排服務器返回202「繼續」或200「完成」。

LoadFromURL('my/resource').then(function(text) { 
    console.log("After a series of $.get requests, the finally delivered text was:\n" + text); 
}); 
+0

我必須得到我的第一個例子錯誤,因爲它看起來確實符合我的預期。謝謝。 – Barguast

0

我不知道如果我理解正確的,因爲你的第二個功能LoadFromText是某種對我黑匣子:

因此,LoadFromURL()可以通過以下方式調用。不過,我認爲,你的結構對於執行的東西來說太臃腫了。嘗試在更少的功能中做到這一點。我做了一個命題:

function Load() { 
    var myUrl = '//path.to/url'; 
    LoadFromUrl(myUrl) 
     .then(LoadFromText, errorHandler) 
     .then(successHandler, errorHandler); 
} 

function successHandler(returnedData) { 
    console.log('Requests were successful: ' + returnedData); 
} 

function errorHandler(err) { 
    console.log('An error occurded: ' + err); 
} 

function LoadFromURL(url) { 
    return $.get(url); 
} 

function LoadFromText(text) { 
    // THIS IS SOME SORT OF BLACK BOX FOR ME... 
    // SEEMS TO RETURN A PROMISE, THOUGH 

    var $deferred = $.Deferred(); 

    // DO THE LOGIC TO EITHER REJECT OR RESOLVE THE PROMISE 

    return $deferred.promise(); 
} 

你只使用主功能Load啓動AJAX鏈。一旦第一個Ajax請求完成,第二個從第一個數據開始。之後,successHandler將根據第二個Ajax調用的數據執行任何所需的操作。這是解決方案的重要補充。
除此之外,它基本上是你做同樣的事情,但分佈到更小的功能,更易於維護。

1

有沒有我可以鏈中的結果

是一個辦法,那就是then默認行爲!

function LoadFromURL(url) { 
    return $.get(url).then(LoadFromText); 
} 

我見過的承諾,使這一部分的實現 - 返回內「那麼」一個承諾,意味着該承諾的最終結果被使用。

jQuery 確實從版本1.8開始支持此行爲。對於1.5到1.7,你可以使用.pipe