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

我有一个简单的事件链:

  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();
};

【问题讨论】:

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


    【解决方案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)
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-27
      • 1970-01-01
      • 1970-01-01
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      相关资源
      最近更新 更多