寻找链接AJAX调用的模式

时间:2014-09-10 13:31:32

标签: javascript ajax design-patterns

我们有一个AJAX Web应用程序,我们拥有的一个常见模式是一个接一个调用的ajax调用。当我们使用多个附加实体保存某些内容时,这很常见。示例可能是 saveCustomer() - > saveCustomerAddress() - >的 saveCustomersOrder()

我们目前拥有它,以便当 methodA()成功时,即第一种方法,它会调用 methodB(),等等(请参阅下面的代码)。这种模式的缺点是很难看到发生了什么。如果您阅读 methodA(),则无法通过阅读方法名称来调用 methodB() methodC()。另一个缺点是,如果你想改变链接,你必须重写大量的代码,如果你只想单独调用一个方法,那么它就无法完成,因为它会调用下游的方法。

function Tester() {
    this.url = 'https://public.opencpu.org/ocpu/library/';

    this.save = function() {
        this.methodA();
    }

    this.methodA = function () {
        var self = this;

        $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {

            //check for errors... and if OK
            alert('A OK');
            self.methodB();

        })
    }
    this.methodB = function () {
        var self = this;

        $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {

            //check for errors... and if OK
            alert('B OK');
            self.methodC();

        })
    }
    this.methodC = function () {
        var self = this;

        $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {
            //OK
            alert('C OK');
        })
    }
}
new Tester().save();

我正在试图找出一个更好的模式。我想你可以在回调函数中包含后面的方法,然后以某种方式将它们传递给每个方法,但我不确定如何处理它。

是否有人知道一种常见的模式类型,您可以在链接方法时删除方法依赖项?

4 个答案:

答案 0 :(得分:3)

function A() {
    writeMessage("Calling Function A");
    return $.ajax({
        url: "/scripts/S9/1.json",
        type: "GET",                    
        dataType: "json"
    });
}


function B(resultFromA) {
    writeMessage("In Function B. Result From A = " + resultFromA.data);
    return $.ajax({
        url: "/scripts/S9/2.json",
        type: "GET",
        dataType: "json"
    });
}


function C(resultFromB) {
    writeMessage("In Function C. Result From B =  " + resultFromB.data);
    return $.ajax({
        url: "/scripts/S9/3.json",
        type: "GET",
        dataType: "json"
    });
}

function D(resultFromC) {
    writeMessage("In Function D. Result From C = " + resultFromC.data);
}

A().then(B).then(C).then(D);

function writeMessage(msg) {
    $("#para").append(msg + "</br>");                 
}

答案 1 :(得分:1)

您可以像这样使用动态调用:

        this.reqChain = ['req_1', 'req_2'];

        this.callChain = function(){
            if(!self.reqChain.length) return;
            ajax({
                url: self.reqChain[0],
                async: true,        
                always: function(processedDataOrXHRWrapper, textStatus, whrWrapperOrErrorThrown){
                   self.reqChain.shift();
                   $(document).trigger('request_'+self.reqChain[0]+'_callback', [processedDataOrXHRWrapper, textStatus, whrWrapperOrErrorThrown])
                   self.callChain();
                }
           });
    }

您可以传递回调,也可以绑定到动态事件。

答案 2 :(得分:1)

这是我对自己问题的回答。我将所有方法包装在函数中,并将回调传递给我的方法。

似乎做了这个工作。有没有人有任何意见?

function Tester2() {

    this.save = function() {

        var self = this;

        var callbackC = function() {
            self.methodC();
        }

        var callbackB = function() {
            self.methodB(callbackC);
        }

        this.methodA(callbackB);

    }

    this.methodA = function (callbackFn) {
        var self = this;

        $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {


            //check for errors... and if OK
            alert('A OK');
            if (callbackFn)
                callbackFn();

        })
    }
    this.methodB = function (callbackFn) {
        var self = this;

        $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {


            //check for errors... and if OK
            alert('B OK');
            if (callbackFn)
                callbackFn();

        })
    }
    this.methodC = function () {
        var self = this;

        $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {
            //OK
            alert('C OK');
        })
    }
}

new Tester2().save();

答案 3 :(得分:0)

试试这个:

function Tester() {
    var self = this;
    this.url = 'https://public.opencpu.org/ocpu/library/';

    this.save = function() {
        self.methodA().then( self.methodB() ).then( self.methodC() )
    }

    this.methodA = function () {
        var self = this;

        return $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {

            //check for errors... and if OK
            alert('A OK');


        })
    }
    this.methodB = function () {
        var self = this;

        return $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {

            //check for errors... and if OK
            alert('B OK');


        })
    }
    this.methodC = function () {
        var self = this;

        return $.ajax({
            url: self.url,
            async: true
        }).always(function (processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {
            //OK

        })
    }
}
new Tester().save();