问题的症结显然在于 B 和 C 之间的关系,总结起来似乎是:
- 如果是B,
pull-C().then(pull-B);
- 如果是C,
pull-B().then(pull-C);
在当前的尝试中,您尝试在pull-B() 和pull-C() 中编写流程逻辑时遇到了问题,这最终是可能的,但很复杂。
一个更简单的策略是使pull_X() 函数非常简单——返回承诺的数据检索器,并在.init() 中的switch/case 结构内编写流逻辑和数据清理。您将在下面的代码中看到我的意思。
除了更简单之外,这还将避免pull_B() 和pull_C() 之间的任何循环依赖。
通过充分利用 Promise,您还会发现:
- 不再需要
this.dfd(支持从函数返回承诺)。
- 对
this.data 的需求消失了(赞成允许承诺传递数据)。
- 不再需要将回调传递给
.pull()(有利于在调用者中链接.then())。因此,回调地狱消失了。
试试这个:
(function($) {
"use strict";
/**
* The Thing
*
* @constructor
*/
function Thing( ) {
/* properties */
this.url = [
/* path */,
/* id */
];
}
Thing.prototype.pull = function(url, args, type) {
return $.ajax({
type: type || 'GET',
url: foo.root + url,
data: $.extend({}, args || {}),
dataType: 'json'
});
};
Thing.prototype.pull_As = function() {
return this.pull('a', this.query);
};
Thing.prototype.pull_A = function() {
this.nav = false;
return this.pull('a/'+ this.url[2]);
};
Thing.prototype.pull_B = function() {
return this.pull('b/' + this.url[2]);
};
Thing.prototype.pull_C = function(id) {
return this.pull('c/' + id || this.url[2]);
};
Thing.prototype.pull_D = function() {
return this.pull_As();
};
Thing.prototype.render = function(data) {
var i, len, html,
that = foo.thing, /* because 'this' is the promise object */
title = document.title.split('|');
for (i = 0, len = title.length; i < len; i += 1) {
title[i] = $.trim(title[i]);
}
title[0] = $.trim(that.title);
document.title = title.join(' | ');
html = Hogan.wrapper.render({
'data': data,
});
$('#thing_wrapper').empty().append(html);
};
Thing.prototype.init = function( ) {
var promise,
that = this;
switch (this.url[1].toLowerCase( )) {
case 'a':
promise = this.pull_A().then(function(data_A) {
/* ... do A data cleanup */
return data_A;//will be passed through to .render()
});
break;
case 'b':
promise = this.pull_C().then(function(data_C) {
//Here an inner promise chain is formed, allowing data_C, as well as data_B, to be accessed by the innermost function.
return that.pull_B().then(function(data_B) {
var data = ...;//some merge of data_B and data_C
return data;//will be passed through to .render()
});
});
break;
case 'c':
var id = ???;
promise = this.pull_C(id).then(function(data_C) {
/* ... do C data cleanup */
return data_C;//will be passed through to .render()
});
break;
case '':
default:
promise = this.pull_D().then(function(data_D) {
/* ... do D data cleanup */
return data_D;//will be passed through to .render()
});
}
promise.then(this.render, console.error.bind(console));
};
window.Thing = Thing;
})(jQuery);
请特别注意,各种函数会返回一个承诺或数据。
我怀疑我的尝试是否 100% 正确。整体结构应该没问题,但您需要仔细查看细节。我可能误解了 B/C 依赖项。运气好的话,它会比我编写的代码更简单。
编辑:根据下面的 cmets 修改代码。