1

将 AJAX 加载指示器插入具有多个 AJAX 调用的语句的最佳方法是什么?

例如:

$("#search_building").on("change blur", function () {
    var building = $("#search_building").val();
    var room = $("#search_room").val();
    var dept = $("#dept").val();
    var dataString = 'room=' + room + '&' + 'building=' + building + '&' + 'dept=' + dept;
    $.ajax({
        type: "POST",
        url: "process_building.php",
        data: dataString,
        cache: false,
        success: function (html) {
            $('#search_room').html(html);
        }
    });
    $.ajax({
        type: "POST",
        url: "process_timetableMon.php",
        data: dataString,
        cache: false,
        success: function (html) {
            $('#grid2_mon').html(html);
        }
    });
         $.ajax({
        type: "POST",
        url: "process_timetableTue.php",
        data: dataString,
        cache: false,
        success: function (html) {
            $('#grid2_tue').html(html);
        }
    });
        $.ajax({
        type: "POST",
        url: "process_timetableWed.php",
        data: dataString,
        cache: false,
        success: function (html) {
            $('#grid2_wed').html(html);
        }
    });
        $.ajax({
        type: "POST",
        url: "process_timetableFri.php",
        data: dataString,
        cache: false,
        success: function (html) {
            $('#grid2_wed').html(html);
        }
    });
        $.ajax({
        type: "POST",
        url: "process_roomList.php",
        data: dataString,
        cache: false,
        success: function (html) {
            $('#list2').html(html);
        }
    });
        }); 
4

3 回答 3

2

从我的博客

随着您的代码库变得越来越难以阅读和维护,使用计数器和其他不合标准的方法将鼓励代码功能障碍。实现这一点的理想方法是使用事件驱动的方法。它更容易维护,并导致更少的意大利面条代码。你可以很容易地实现这样的事情:

//First, we need an object that will contain our 'event domain'
var EventDomain = new function(config,callback){

this.__listeners = {}; //this will store references to functions associated to events

this.on = function(event,listener){ //here, we provide a member that binds 
                                    //a 'listener' function to an event string
    if (typeof this.__listeners[event] == "undefined"){
        this.__listeners[event] = [];
    }
    this.__listeners[event].push(listener);
};
this.emit = function(event,params){ //here, we provide a member that 'emits' an
                                    //event string, calling any 'listener' functions
                                    //and passing a parameter object 
                                    //{param1: val1, param2:val2, paramN, valN} 
    if(typeof event == "string"){
        event = { type: event };
    }
    if(!event.target){
        event.target = this;
    }

    if(!event.type){
        throw new Error("Event object missing 'type' property.");
    }
    if(this.__listeners[event.type] instanceof Array){
        var listeners = this.__listeners[event.type];
        for (var i=0, len=listeners.length; i < len; i++){
            listeners[i](params);
        }
    }
};
this.removeListener = function(type, listener){ //here, we provide a member that allows
                                                //us to remove a 'listener' function 
                                                //from an event
    if(this.__listeners[type] instanceof Array){
        var listeners = this.__listeners[type];
        for (var i=0, len=listeners.length; i < len; i++){
            if (listeners[i] === listener){
                listeners.splice(i, 1);
                break;
            }
        }
    }
};
this.removeAllListeners = function(type){ //here, we provide a member that allows
                                          //us to remove ALL 'listener' functions
                                          //from an event
    if(this.__listeners[type] instanceof Array){
        delete this.__listeners[type];
    }
};
};

现在我们有了一个事件域,我们可以将它与上面的代码片段一起使用。但首先,让我们创建一个对象来充当我们的 ajax 调用的控制器:

var AjaxController = new function(){  
    var counter;  //create a private member called counter
    this.onLoad = function(fn){ //here, we provide a member to specify what to do
                                //when ajax requests begin
        EventEmitter.on('ajax_loading',(function(fn){ //bind 'ajax_loading' event to an  
                                                      //ajax loading indicator
            return function(){ //yet another closure
                if(counter<1){ //obviously, we only want to do something on the first
                               //load, not every single time.  Otherwise, you'll end
                               //end up trying to show the exact same loading animation
                               //for each ajax call
                    fn();
                }
                counter++;
            };
        })(fn));
    };

    this.onComplete = function(fn){ //here we provide a member to specify what to do
                                    //when ALL ajax requests have finished
        EventEmitter.on('ajax_complete',(function(fn){ //bind the 'ajax_complete' event 
                                                       //to a loading indicator
            return function(){ //yet another closure
                counter--; //decrement concurrent loading
                if(counter<1){ //its only finished once the counter is 0!
                   fn();
                }
            }
        })(fn));
    };

    var constructor = function(){ //good object oriented programming uses constructors!
        counter = 0;
        //Now, lets overload the original $.ajax method to provide functionality
        //for our event driven approach
        $.ajax = (function(ajax){ //this is called a 'closure'.  
                                  //We pass it the original function and it wraps and 
                                  //returns it, overloading the original method                                       
            function overloadAjax(params){ //this is our overloading function
                  if(params.success){ //if there is a success parameter passed
                                      //to the ajax call, overload that as well
                                      //to emit the 'ajax_complete' event
                     params.success = (function(success){
                         function overloadSuccess(data){
                             EventDomain.emit('ajax_complete');
                             success(data);
                         }
                         return overloadSuccess; //return and overload success
                     })(params.success);
                  }
                  EventDomain.emit('ajax_loading'); //emit the 'ajax_loading' event
                                                    //for each ajax call
                  ajax(params);
            }
            return overloadAjax; //here we return 'overload' back to $.ajax, overloading       
                                 //the original
        })($.ajax);


    }
    constructor(); //we call the constructor after all members have been prototyped 
}

现在我们已经为自己创建了一个很好的、可重用的 ajax 加载器工具包,让我们使用它:

AjaxController.onLoad(function(){
   //put some code here to do DOM manipulation to add a loader, or however you
   //want to 'indicate' ajax loading
});

AjaxController.onComplete(function(){
   //put some code here to do some DOM manipulation to remove your loader, or however
   //you want to 'indicate' that ajax loading is complete
});

现在,它只是工作:

$("#search_building").on("change blur", function () {

var building = $("#search_building").val();
var room = $("#search_room").val();
var dept = $("#dept").val();
var dataString = 'room=' + room + '&' + 'building=' + building + '&' + 'dept=' + dept;
$.ajax({
    type: "POST",
    url: "process_building.php",
    data: dataString,
    cache: false,
    success: function (html) {
        $('#search_room').html(html);
    }
});
$.ajax({
    type: "POST",
    url: "process_timetableMon.php",
    data: dataString,
    cache: false,
    success: function (html) {
        $('#grid2_mon').html(html);
    }
});
     $.ajax({
    type: "POST",
    url: "process_timetableTue.php",
    data: dataString,
    cache: false,
    success: function (html) {
        $('#grid2_tue').html(html);
    }
});
    $.ajax({
    type: "POST",
    url: "process_timetableWed.php",
    data: dataString,
    cache: false,
    success: function (html) {
        $('#grid2_wed').html(html);
    }
});
    $.ajax({
    type: "POST",
    url: "process_timetableFri.php",
    data: dataString,
    cache: false,
    success: function (html) {
        $('#grid2_wed').html(html);
    }
});
    $.ajax({
    type: "POST",
    url: "process_roomList.php",
    data: dataString,
    cache: false,
    success: function (html) {
        $('#list2').html(html);
    }
});
    }); 

在前端将事件驱动编程与面向对象编程相结合的巨大好处是,您最终可以让您的开发人员腾出更多的时间来进行更多的实际内容创建和更少的问题解决。创建一个可重用的框架需要更多的时间开始,但在未来会有指数级的时间/质量优势。如果您想在这些概念方面获得更多帮助,请随时给我发电子邮件:rhyneandrew@gmail.com。我很乐意免费为您提供帮助;)

于 2013-02-17T05:18:02.463 回答
0

您可以使用计数器来记录正在进行的 AJAX 请求的数量。当计数器大于 1 时,显示加载指示器。每次收到响应,减 1。当计数器达到 0 时,隐藏加载指示器。

于 2013-02-17T04:18:42.657 回答
0

$.ajax()您可以在通话中使用类似这样的东西:

$.ajaxSetup({
    beforeSend:function(){
        // show image here
        $("#busy").show();
    },
    complete:function(){
        // hide image here
        $("#busy").hide();
    }
});
于 2013-02-17T04:25:17.483 回答