为什么没有设置选项时,AJAX beforeSend和complete函数会多次触发

时间:2014-08-08 11:38:55

标签: javascript jquery ajax prototype

我在原型函数中使用jQuery Ajax request。我希望用户能够将自己的completebeforeSend函数传递给此函数。然后应该从选项中提取这些用户函数并将其放入我自己的beforeSendcomplete函数中,这样我就可以在触发用户函数之前在其中执行一些系统内容。

我做了这个小提琴来澄清。查看“使用选项”链接如何按预期工作,而“无选项”链接则不然。点击几次,看看我的意思:

http://jsfiddle.net/xwmoaepc/1/

function jBox() {
    this.options = {
        ajax: {
            url: 'http://stephanwagner.me/ajax/0/SYSTEM RESPONSE',
            data: ''
        }
    }
}

jBox.prototype.ajax = function (options) {

    $('#log').append('<div class="first">function prototype.ajax started<div>');

    // Abort running ajax call
    this.ajaxRequest && this.ajaxRequest.abort();

    // Merge options
    var ajaxOptions = jQuery.extend(this.options.ajax, (options || {}));

    // Extract events
    var beforeSend = ajaxOptions.beforeSend || function () {};
    var complete = ajaxOptions.complete || function () {};

    // Set new beforeSend event
    ajaxOptions.beforeSend = function () {

        $('#log').append('<div style="color: #d66">SYSTEM-beforeSend<div>');

        (beforeSend.bind(this))();
    }.bind(this);

    // Set new complete event 
    ajaxOptions.complete = function (response) {

        $('#log').append('<div style="color: #6d6">SYSTEM-complete: ' + response.responseText + '<div>');

        (complete.bind(this))(response);
    }.bind(this);

    // Send new ajax request
    this.ajaxRequest = jQuery.ajax(ajaxOptions);
};

// Create instance
var jBox = new jBox();

// This function is working!
function triggerAjaxOpt() {

    var userOptions = {
        url: 'http://stephanwagner.me/ajax/0/USER RESPONSE: ' + $('input').val(),
        beforeSend: function () {
            $('#log').append('<div style="color: #66d">USER-beforeSend<div>');
        },
        complete: function () {
            $('#log').append('<div style="color: #66d">USER-complete<div>');
        }
    };

    jBox.ajax(userOptions);
}

// This function will have more and more beforeSend and complete outputs
function triggerAjax() {
    jBox.ajax();
}

另请注意,单击无效链接后更改数字2到3时,不会更改响应。

编辑:它现在正在运行,这就是我最终的结果: http://jsfiddle.net/xwmoaepc/3/

1 个答案:

答案 0 :(得分:2)

试试这个,它会起作用:

var ajaxOptions = jQuery.extend((options || {}), this.options.ajax);

如果你有this.options.ajax作为扩展它的第一个参数,那么ll mutate this.options.ajax见下面的代码:

//see what the following line does when second argument is an object
//  not having beforesend (if it has then it'll be overwritten)
//var ajaxOptions = jQuery.extend(this.options.ajax, (options || {}));
var org = {id:"org"}
var copy = jQuery.extend(org,{});
console.log(copy===org);//true as copy is a reference to org
copy.id="copy";//mutating members in copy affect org
console.log(org.id);//=copy

现在声明:

ajaxOptions.beforeSend = function () { ...

与:

相同
this.options.ajax.beforeSend = function() { ...

所以第一次它是未定义的,而局部变量beforeSend将是一个空函数。

第二次局部变量beforeSend将是this.options.ajax.beforesend和this.options.ajax.beforesend重新分配一个调用局部变量beforesend的函数,该函数将调用closesent(空函数)< / p>

你第三次打电话给ajax ......