2012-07-18 25 views
13

Tôi có một chuỗi đơn giản của sự kiện:Chuỗi Jquery Promises

  1. Nhận Cột từ một bảng siêu dữ liệu (async)
  2. cột chọn tải (async)
  3. làm cho danh sách

Tôi đã từng chỉ sử dụng chuỗi các chức năng này, mỗi chức năng gọi là tiếp theo khi nó đã hoàn thành. Tuy nhiên, nó không phải là rất rõ ràng những gì đang xảy ra (gọi getColumnsFromMeta kết quả trong quan điểm được dân cư). Vì vậy, vì lợi ích của sự rõ ràng và sử dụng lại mã tôi muốn cấu trúc lại chúng bằng cách sử dụng JQueryPromises. Tôi đã sử dụng lời hứa trước đây. Nhưng làm cách nào để chuỗi hơn hai? getColumnsFromMeta().then(loadSourceFromDatabase /*some arguments*/) //.then(renderList)?;

Dưới đây là một ví dụ về 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(); 
}; 

Trả lời

27

Nó phải là một cái gì đó như:

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/ - đây là một mẫu làm việc

http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/ - đây là bài viết Tôi thực sự thích về lời hứa

+0

Cảm ơn bạn đã trả lời nhanh nó hoạt động rất tốt! Và cảm ơn cho bài viết, nó có vẻ tốt. Là một câu hỏi bổ sung: có thể chuỗi .done/.always vv trên đường ống ở các giai đoạn khác nhau không? – JonWells

+0

@CrimsonChin: vâng. PS: cho tôi một giây, jsfiddle sẽ được thực hiện trong một thời điểm – zerkms

+0

@CrimsonChin: có, bạn có thể sử dụng bất kỳ của chúng, miễn là 'ống()' trả về chậm là tốt. PS: Tôi đã thêm ví dụ jsfiddle – zerkms

4

Trả lời của zerkms đã giúp tôi sau một vài suy nghĩ. Tôi sẽ đăng những gì tôi đã làm ở đây trong trường hợp một ví dụ với bối cảnh đầy đủ là hữu ích.

/** 
* 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) 
});