修改jQuery jsonp回调函数?

时间:2014-03-05 01:28:18

标签: jquery ajax callback jsonp

我想我会被困在写一个凌乱的派遣功能,但我想我会检查S.O.社区首先要看是否有人提出了一个更容易的解决方案。

祝世界银行拥有开放的API,但它们存在一些实施问题。第一个问题是他们的服务器没有实现CORS Access-Control-Allow-Origin: *,所以这意味着JSONP而不是JSON。这不会是一个问题,除了他们保留回调函数的情况!举一个具体的例子,我在我的代码中提出以下请求:

var deferredRegionsRequest = $.getJSON(
    "http://api.worldbank.org/regions/?prefix=?",
    {format: "jsonp"}
);

(是的,他们使用参数prefix而不是传统的callback。)

jQuery尽职尽责地创建一个随机回调函数,并将AJAX请求发布为:

http://api.worldbank.org/regions/?prefix=jQuery18308848262811079621_1393981029347&format=jsonp&_=1393981029990

请注意,回调函数具有大写Q

然而,世界银行返回的回复已将该回调重命名为全部小写!

jquery18308848262811079621_1393981029347([
    { "page": "1", "pages": "1", "per_page": "50", "total": "32" },
    [ {
        "id": "",
        "code": "AFR",
        "name": "Africa"
      }, {
...

显然这不起作用。如果我只是发出一个请求,那么提供我自己的回调函数并使用jsonpCallback的{​​{1}}参数并不会太痛苦。不幸的是,我需要遍历和遍历他们的REST API,因此我将进行数十次(并行)API调用。我检查了一个自定义回调,$.ajax()设置为全局this对象,因此单个回调函数似乎没有任何明显的方法来管理多个响应。看起来我可能会遇到一个混乱的自定义调度程序实现,我真的很想避免。

我到目前为止唯一的选择是定义一个window回调,它接受完全填充的URL,解析它以找到回调函数(beforeSend),创建一个新的回调动态函数,它是原始(jQuery...)的全小写版本,并且通过调用原始函数不执行任何操作。黑客商数是如此之高我的头脑旋转,但我已经证实这确实有效:

jquery...

我当然希望我错过了一些非常简单的东西,非常善良的人会向我指出。

1 个答案:

答案 0 :(得分:4)

你称之为hack的最后一个选择听起来像是一个强大的简单方法来利用jQuery为你做的所有事情,只需通过制作你自己的小写函数并从中调用混合大小写来解决一个案例问题。除了让世界银行修理他们的服务器之外,这似乎是对我做事的最不具干扰性的方式。我看不到任何更好的解决方法。

如果jQuery回调函数已经在beforeSend时存在,那么您需要做的就是创建一个具有小写名称的全局变量,并在其中添加对混合外壳函数的引用。您甚至不必创建函数体。

因此,如果您在jQuery18308848262811079621_1393981029347中的网址中看到beforeSend,那么您只需执行以下操作:

window.jquery18308848262811079621_1393981029347 = jQuery18308848262811079621_1393981029347;

我想可能需要eval()来完成这项工作,因为你将函数的名称作为字符串。或许这里的一个天才可以弄清楚如何在没有eval()的情况下创建这行代码。


另一种选择可能是对你使用的jQuery库进行单个字符补丁,因此它只输出一个小写字符串。

我认为“jQuery”字符串部分来自于:

jQuery.extend({
// Unique for each copy of jQuery on the page
expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),

虽然需要一些调试才能确认。


或者,看起来好像有一个回调函数可以创建可以修改或替换的jsonpCallback名称:

// Default jsonp settings
jQuery.ajaxSetup({
    jsonpCallback: function() {
        var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
        this[ callback ] = true;
        return callback;
    }
});

我发现这可以在我的演示JSONP应用http://jsfiddle.net/jfriend00/UM9NL/中使用:

$.ajaxSetup({
  beforeSend: function(xhr, settings) {
      var origCallback = settings.jsonpCallback;
      settings.url = settings.url.replace(/=jQuery/, "=jquery");
      window[origCallback.toLowerCase()] = function() {
          window[origCallback].apply(this, arguments);
      }
  }
});

而且,这也有效http://jsfiddle.net/jfriend00/GXte2/

// Default jsonp settings
(function() {
    var myajax_nonce = jQuery.now();
    jQuery.ajaxSetup({
        jsonp: "callback",
        jsonpCallback: function() {
            var callback = ( jQuery.expando.toLowerCase() + "_" + ( myajax_nonce++ ) );
            this[ callback ] = true;
            return callback;
        }
    });
})();