Jquery承诺链

我有一个简单的事件链:

  1. 从metaData表中获取列(异步)
  2. 加载选定的列(异步)
  3. 渲染列表

我曾经只是链接这些函数,每个函数在完成后调用它们。 然而,它不是很明显(在填充视图时调用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(); }; 

它应该是这样的:

 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/ – 这是我非常喜欢的承诺文章

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