javascript - 为什么在没有设置选项的情况下AJAX beforeSend和complete函数会被多次触发

标签 javascript jquery ajax prototype

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

我做了这个 fiddle 来澄清。查看“带选项”链接如何按预期工作,而“不带选项”链接如何不按预期工作。单击几次即可明白我的意思:

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/

最佳答案

试试这个,它会起作用:

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

如果你将 this.options.ajax 作为扩展的第一个参数,它会改变 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的函数,该函数将调用闭包beforesent(空函数)

第三次调用ajax...

关于javascript - 为什么在没有设置选项的情况下AJAX beforeSend和complete函数会被多次触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25202669/

相关文章:

javascript - HTML5 拖放与 jQuery UI 拖放

javascript - 聊天文本自动向下滚动并从数据库加载信息

javascript - 在 Protractor 配置文件中设置 onPrepare 时一直报错

javascript - 当我在 React 应用程序上执行 npm start 时,不断收到 "? Something is already running on port 3000"

javascript - 使用 jquery 将用户滚动到移动设备上单击的选项卡

javascript - jQuery Scrollify - 第一部分忽略偏移量

javascript - 数字插入数据库,但不插入字符或数字/字符

javascript - 无法通过 ajax jQuery 将信息发送到 PHP 页面

java - 正则表达式:匹配并替换字符串中的模式,同时将匹配字符串的一部分保留在替换字符串中

javascript - 如何使用扩展语法将数组传递给 JavaScript 中的方法