Jquery 承诺链

Posted

技术标签:

【中文标题】Jquery 承诺链【英文标题】:Chain of Jquery Promises 【发布时间】:2012-07-17 09:13:13 【问题描述】:

我有一个简单的事件链:

    从元数据表中获取列(异步) 加载选定的列(异步) 渲染列表

我过去只是链接这些函数,每个函数在完成后调用下一个函数。但是,发生了什么并不是很明显(调用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();
;

【问题讨论】:

【参考方案1】:

应该是这样的:

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/ -- 这是我非常喜欢的关于 Promise 的文章

【讨论】:

感谢您的快速回复,效果很好!感谢您的文章,它看起来不错。作为一个额外的问题:是否可以将 .done/.always 等链接到不同阶段的管道? @CrimsonChin:是的。 PS:等一下,jsfiddle马上就搞定了 @CrimsonChin:是的,你可以使用其中任何一个,只要pipe() 也返回延迟。 PS:我添加了jsfiddle示例 @pcv:我提出这个答案还不到一年前 使用 jQuery 1.8 及更高版本,您可以将 'pipe' 替换为 'then',正如 @pcv 正确提到的那样【参考方案2】:

经过一番思考,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)
);

【讨论】:

以上是关于Jquery 承诺链的主要内容,如果未能解决你的问题,请参考以下文章

承诺链中承诺之间的延迟

复杂承诺返回链中的承诺 catch() 顺序

异常被承诺链吞噬

等待承诺链有啥问题?

拒绝后承诺链继续

Angularjs 承诺拒绝链