以下是我当前的代码:https://gist.github.com/benjamw/f6d5d682caddd4c1e506
我尝试做的是:根据用户点击页面时的URL,从服务器下载不同的数据,完成所有操作后,使用Hogan呈现页面
我的问题是,步骤B需要来自步骤C的数据才能正确呈现,而步骤C需要来自步骤B的数据来提取正确的数据,但如果该页面是用户,则步骤C可以自行提取请求(C直接转到C所需的数据是URL的一部分。)
我Deferred
存储Thing
,可以在各种拉动步骤中解析并触发渲染,但在pull_B
中,我不希望它被解决,直到pull_B
它获取并清除pull_C
和when
的数据。但是如果用户直接通过C,那么我希望它解决得很好。
当进程通过B路径包含C路径时,如何向init()
函数中的SELECT P.nome, centroide_produto_id, similar_produto_id,
(SELECT preco_venda FROM precos A
WHERE A.produto_id=CL.similar_produto_id
AND A.preco_id = (
SELECT Max(preco_id) FROM precos A2, cluster_copy3 CL2 WHERE A2.produto_id=A.produto_id AND A2.produto_id=CL2.similar_produto_id
AND A2.preco_venda = (SELECT Max(preco_venda) FROM precos A3, cluster_copy3 CL3 WHERE A3.produto_id=CL3.similar_produto_id AND CL3.centroide_produto_id=CL.centroide_produto_id)
)
) AS preco_maximo
FROM produtos P, cluster_copy3 CL
WHERE P.produto_id=CL.centroide_produto_id
AND CL.centroide_produto_id IN (9817, 9816)
#GROUP BY CL.centroide_produto_id
动态添加承诺?
或者,我怎样才能让B将它的承诺传递给C然后在那里解决它,但仍然保持能够通过C本身的功能,并让它仍然解决主延迟对象而不去先通过B?
我真的很难不为此而陷入回调地狱,但我发现很难这样做。
答案 0 :(得分:1)
问题的症结显然是B和C之间的关系,总的来说,似乎是:
pull-C().then(pull-B)
; pull-B().then(pull-C)
; 在当前的尝试中,您通过尝试编写pull-B()
和pull-C()
内的流逻辑来解决问题,这最终可能但很复杂。
更简单的策略是使pull_X()
函数非常简单地承诺返回数据检索器,并在.init()
中对switch / case结构内的流逻辑和数据清理进行编码。您将在下面的代码中看到我的意思。
除了更简单之外,这还可以避免pull_B()
和pull_C()
之间出现循环依赖的可能性。
通过充分利用承诺,您还会发现:
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);
特别注意从各种函数返回一个promise或数据。
我怀疑我的尝试是100%正确的。整体结构应该没问题,但您需要仔细查看细节。我可能误解了B / C依赖关系。幸运的是,它会比我编码的更简单。
编辑:根据以下评论修改代码。