Chain of Jquery Promises

ぐ巨炮叔叔 提交于 2019-12-30 03:59:10

问题


I have a simple chain of events:

  1. Get Columns from a metaData table (async)
  2. load selected columns (async)
  3. render list

I used to just the chain these functions, each calling the next when it had completed. However, its not very obvious what's going (calling getColumnsFromMeta results in the view being populated). So in the interest of clarity and code re-use I'd like to refactor these using JQuery Promises. I have used promises before. But how do I chain more than two? getColumnsFromMeta ().then(loadSourceFromDatabase /*some arguments*/) //.then(renderList)?;

Here's an example of the 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:


It should be something like:

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/ - here is a working sample

http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/ -- this is the article I really like about promises




回答2:


zerkms's reply helped me after some thought. I'm going to post what I did here in case an example with full context is helpful.

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


来源:https://stackoverflow.com/questions/11539605/chain-of-jquery-promises

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!