2012-07-18 61 views
13

我有事件的一個簡單鏈:鏈的jQuery少輝

  1. 獲取從元數據表中的列(異步)
  2. 負荷選中的列(異步)
  3. 渲染列表

我習慣了鏈式這些功能,每個功能完成後都會調用下一個功能。然而,它不是很明顯發生了什麼(在視圖中填入getColumnsFromMeta結果)。所以爲了清晰起見和代碼重用,我想用JQueryPromises來重構這些。我之前使用過承諾。但是,我如何鏈接兩個以上? getColumnsFromMeta().then(loadSourceFromDatabase /*some arguments*/) //.then(renderList)?;

這裏的getColumnsFromMeta的例子:

var getColumnsFromMeta = function(id) 
{ 
    var sql, 
     dfd; 

    dfd = $.Deferred(); 

    var onSuccess = function(tx, result) 
    { 
     var columns = []; 

     for (var i = 0; i < result.rows.length; i++) 
     { 
      columns.push(result.rows.item(i).Column); 
     } 

     dfd.resolve(columns); 
    }; 

    var onError = function(tx, error) 
    { 
     dfd.reject(error); 
    }; 

    sql = "SELECT Column FROM Meta WHERE id = ?"; 

    database.query(sql, [id], onSuccess, onError); 

    return dfd.promise(); 
}; 

回答

27

它應該是這樣的:

function getColumnsFromMeta() 
{ 
    var d = $.Deferred(); 

    // retrieve data in async manner and perform 
    // d.resolve(columns); 

    return d.promise(); 
} 

function loadSelectedColumns(columns) 
{ 
    var d = $.Deferred(); 

    // retrieve data in async manner and perform 
    // d.resolve(data); 

    return d.promise(); 
} 

function render(data) 
{ 
    // render your data 
} 

getColumnsFromMeta().pipe(loadSelectedColumns).pipe(render); 

http://jsfiddle.net/zerkms/xYDbm/1/ - 這裏是工作示例

http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/ - 這是文章我很喜歡約定

+0

感謝您的快速回復它很好!感謝這篇文章,它看起來不錯。作爲一個額外的問題:是否有可能將.done/.way等鏈接到不同階段的管道上? – JonWells 2012-07-18 10:56:43

+0

@CrimsonChin:是的。 PS:給我一秒,jsfiddle將在一瞬間完成 – zerkms 2012-07-18 10:58:16

+0

@CrimsonChin:是的,只要'pipe()'返回延遲,你也可以使用它們中的任何一個。 PS:我添加了jsfiddle示例 – zerkms 2012-07-18 11:03:09

4

zerkms的回覆經過一番思考後幫了我。我將發佈我在這裏所做的事情,以便全範圍的示例有幫助。

/** 
* takes a list of componentIDs to load, relative to componentRoot 
* returns a promise to the map of (ComponentID -> componentCfg) 
*/ 
function asyncLoadComponents (componentRoot, components) { 

    var componentCfgs = {}; 

    function asyncLoadComponentCfg(component) { 
     var url = _.sprintf("%s/%s", componentRoot, component); 
     var promise = util.getJSON(url); 
     promise.done(function(data) { 
      componentCfgs[component] = data; 
     }); 
     return promise; 
    } 

    var promises = _.map(components, asyncLoadComponentCfg); 
    var flattenedPromise = $.when.apply(null, promises); 
    var componentCfgPromise = flattenedPromise.pipe(function() { 
     // componentCfgs is loaded now 
     return $.Deferred().resolve(componentCfgs).promise(); 
    }); 

    return componentCfgPromise; 
} 


var locale = 'en-US'; 
var componentRoot = '/api/components'; 
var components = ['facets', 'header', 'DocumentList']; 
$.when(asyncLoadComponents(componentRoot, components)).done(function(componentCfgs) { 
    buildDocumentListPage(locale, componentCfgs) 
});