【问题标题】:jQuery's .ajaxSend: can't add data dynamicallyjQuery 的 .ajaxSend:不能动态添加数据
【发布时间】:2015-02-27 05:02:10
【问题描述】:

如有必要,我使用$(document).ajaxSend(...) 将数据(POST args)动态添加到某些 Ajax 请求中。 当$.ajax(...) 调用中定义了一些数据时,添加数据有效。但是如果$.ajax设置中没有定义数据,我的$.ajaxSend就无法在设置中添加数据。

这是我的$.ajaxSend拦截器:

$(document).ajaxSend(function(e, request, settings) {
    if(settings.csrfIntention) {
        var requestToken = {
            intention: settings.csrfIntention,
            hash: self.tokens[settings.csrfIntention]
        }

        if(!settings.data) {
            settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
        }
        else if(typeof(settings.data) == 'string') {
            settings.data += '&_token=' + encodeURIComponent(JSON.stringify(requestToken));
        }
        else if(!settings.data._token) {
            settings.data._token = requestToken;
        }
    }
});

还有一个有效的 $.ajax 调用示例:

$.ajax({
    url: opts.close.url,
    method: 'POST',
    data: { foo:'bar' },
    csrfIntention: 'ajax_close_ticket',
    success: function(data) { ... }
});

$.ajaxSend 有效,settings.data 设置为:

foo=bar&_token=%7B%22intention%22%3A%22ajax_close_ticket%22%2C%22hash%22%3A%22uXV1AeZwm-bZL3KlYER-Dowzzd1QmCmaT6aJFjWLpLY%22%7D

服务器端,我可以检索两个字段:foo 和 _token。

现在,如果我在 $.ajax 调用中删除 data 对象,$.ajaxSend 的输出似乎也可以:

 _token=%7B%22intention%22%3A%22ajax_close_ticket%22%2C%22hash%22%3A%225cK2WIegwI6u8K_FrxywuauWOo79xvhIcASQrZ9QPZQ%22%7D

但是,服务器没有收到我的 _token 字段:(

另一个有趣的事实:当我拥有这两个字段时,“网络”选项卡下的 Chromium 开发工具会在“表单数据”标题下显示这两个字段。单独使用 _token 时,“Form Data”替换为“Request Payload”。

编辑:刚刚明白为什么_token 不被服务器解释。如果之前在$.ajax 调用中没有设置数据,jQuery 不会在 HTTP 标头中添加正确的Content-Type,它会将其设置为text/plain 而不是application/x-www-form-urlencoded。如何强制 jQuery 添加此标头?

编辑 2: 找到解决方案。将发布答案以帮助其他人...

【问题讨论】:

    标签: javascript jquery ajax


    【解决方案1】:

    我为我糟糕的英语道歉

    我相信他的情况的解决方案是使用函数“ajaxSetup”

    var requestToken = {
            intention: settings.csrfIntention,
            hash: self.tokens[settings.csrfIntention]
    };
    
    $.ajaxSetup({
        data : {
            _token: requestToken
        }
    });
    

    这样你所有的订单都以数据为愿望

    【讨论】:

    • 谢谢,但我不想在所有请求中添加 _token。我认为$.ajaxSend 更适合我的情况。但是,我理解了这个问题(阅读我对 OP 的编辑),我会发布一个答案。
    【解决方案2】:

    更简单的方法:

    var requestToken = {
            intention: settings.csrfIntention,
            hash: self.tokens[settings.csrfIntention]
        }
    var myForm = {};
    myForm['_token'] = encodeURIComponent(JSON.stringify(requestToken));
    

    在您的 ajax 调用中:

    myForm['foo'] = 'bar';
    $.ajax({
        url: opts.close.url,
        method: 'POST',
        data: myForm,
        csrfIntention: 'ajax_close_ticket',
        success: function(data) { ... }
    });
    //This sends foo and _token
    

    【讨论】:

    • 谢谢,但我找到了解决方案(将我的编辑读入 OP)。无论如何,您的解决方案不会很容易在我的应用程序中实现(我简化了代码)。无论如何,谢谢你,很抱歉让你浪费时间!
    • 没问题@MorganTouvreyQuilling ...我很乐意提供帮助...干杯:)
    【解决方案3】:

    我终于在 10 分钟后回答了我的问题……

    在 HTTP 中,表单参数被发送到请求正文中的标题下。应该存在标头Content-Type 来声明数据类型。当此标头设置为 application/x-www-form-urlencoded 时,服务器将理解您发送了一个表单并将请求正文解析为 GET URL(您知道,foo=bar&key=val 格式)。

    当您在$.ajax 调用中设置data 对象时,jQuery 会自动添加此标头。然后它将请求传递给$.ajaxSend 回调,该回调会添加其适当的字段。

    当请求设置中没有提供data 时,jQuery 不会在请求标头中添加不必要的Content-Type: x-www-form-urlencoded。然后,当您将请求正文附加到您的$.ajaxSend 回调中时,jQuery 不会再次检查数据并将内容声明为text/plain。服务器与text/plain 无关,因此它不会将正文数据解释为表单字段。

    你显然可以强制jQuery将标题更改为application/x-www-form-urlencoded,让我们拿我原帖的代码:

    if(!settings.data) {
        settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
    }
    

    现在添加正确的标题:

    if(!settings.data) {
        settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
        request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    }
    

    【讨论】:

      猜你喜欢
      • 2014-01-26
      • 2014-10-17
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-15
      相关资源
      最近更新 更多