Jquery承诺链

时间:2012-07-18 10:46:40

标签: javascript jquery jquery-deferred promise jquery-chaining

我有一个简单的事件链:

  1. 从元数据表(异步)
  2. 获取列
  3. 加载选定的列(异步)
  4. 渲染列表
  5. 我过去只是将这些函数链接起来,每个函数在完成后都会调用它们。然而,它不是很明显(调用getColumnsFromMeta会导致视图被填充)。因此,为了清晰和重复使用代码,我想使用JQuery Promises重构这些内容。我以前用过承诺。但是我如何连锁超过两个? 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();
    };
    

2 个答案:

答案 0 :(得分: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/ - 这是我非常喜欢承诺的文章

答案 1 :(得分: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)
});