使用延迟动态添加顺序操作

时间:2015-08-11 23:02:38

标签: javascript jquery deferred .when

以下是我当前的代码:https://gist.github.com/benjamw/f6d5d682caddd4c1e506

我尝试做的是:根据用户点击页面时的URL,从服务器下载不同的数据,完成所有操作后,使用Hogan呈现页面

我的问题是,步骤B需要来自步骤C的数据才能正确呈现,而步骤C需要来自步骤B的数据来提取正确的数据,但如果该页面是用户,则步骤C可以自行提取请求(C直接转到C所需的数据是URL的一部分。)

Deferred存储Thing,可以在各种拉动步骤中解析并触发渲染,但在pull_B中,我不希望它被解决,直到pull_B它获取并清除pull_Cwhen的数据。但是如果用户直接通过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?

我真的很难不为此而陷入回调地狱,但我发现很难这样做。

1 个答案:

答案 0 :(得分:1)

问题的症结显然是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()之间出现循环依赖的可能性。

通过充分利用承诺,您还会发现:

  • 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或数据。

我怀疑我的尝试是10​​0%正确的。整体结构应该没问题,但您需要仔细查看细节。我可能误解了B / C依赖关系。幸运的是,它会比我编码的更简单。

编辑:根据以下评论修改代码。