javascript Jquery 承诺链

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11539605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 13:35:30  来源:igfitidea点击:

Chain of Jquery Promises

javascriptjqueryjquery-deferredpromisejquery-chaining

提问by Jon Wells

I have a simple chain of events:

我有一个简单的事件链:

  1. Get Columns from a metaData table (async)
  2. load selected columns (async)
  3. render list
  1. 从元数据表中获取列(异步)
  2. 加载选定的列(异步)
  3. 渲染列表

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 getColumnsFromMetaresults in the view being populated). So in the interest of clarity and code re-use I'd like to refactor these using JQueryPromises. I have used promises before. But how do I chain more than two? getColumnsFromMeta ().then(loadSourceFromDatabase /*some arguments*/) //.then(renderList)?;

我曾经只是将这些函数链接起来,每个函数在完成后调用下一个函数。但是,发生了什么并不是很明显(getColumnsFromMeta在填充的视图中调用结果)。因此,为了清晰和代码重用,我想使用JQueryPromises. 我以前使用过承诺。但是我如何链接两个以上?getColumnsFromMeta ().then(loadSourceFromDatabase /*some arguments*/) //.then(renderList)?;

Here's an example of the getColumnsFromMeta:

下面是一个例子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();
};

回答by zerkms

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://jsfiddle.net/zerkms/xYDbm/1/- 这是一个工作示例

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

http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/——这是我非常喜欢关于承诺的文章

回答by Dustin Getz

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.

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