javascript - jQuery 中的并行 JSONP 请求不会触发多个 "callback events"?

标签 javascript ajax jquery jsonp

当我执行多个 jsonp 请求时,我遇到了 jQuery 问题,所有请求都具有相同的 jsonpCallback 函数。似乎只有其中一个回调函数被触发。 JSONP 请求是否以某种方式相互覆盖?

下面是一个向 github 发出 2 个 jsonp 请求的示例,即使两个 firebug 都显示它们都返回,回调函数 getName 只为其中一个调用:

function getName(response){
    alert(response.data.name);
}

function userinfo(username){
    $.ajax({
        url: "https://api.github.com/users/" + username,
        jsonpCallback: 'getName',
        dataType: "jsonp"
    });        
}

users = ["torvalds", "twitter", "jquery"]
for(var i = 0; i < users.length; i++){
  userinfo(users[i]);
}

最佳答案

由于 jsonp 的工作原理,您的请求只触发了一次。

Jsonp 意味着从外部域向页面添加脚本标记,以绕过现代浏览器(现在是 IE6 和 2011 年 4 月的 IE6 和 7)内置的跨站点脚本保护。为了让该脚本与页面上的其余脚本交互,加载的脚本需要调用页面上的函数。该函数必须存在于全局命名空间中,这意味着只能有一个具有该名称的函数。换句话说,如果没有 JQuery,单个 jsonp 请求将如下所示:

<script>
function loadJson(json) {
    // Read the json
}
</script>
<script src="//outsidedomain.com/something.js"></script>

something.js 看起来像这样:

loadJson({name:'Joe'})

在这种情况下,something.js 有一个硬编码的回调来加载它携带的 JSON,页面有一个硬编码的 loadJson 函数等待像这样的脚本加载和调用它。

现在假设您希望能够从多个来源加载 json 并告知每个来源何时完成,或者甚至多次从同一来源加载 JSON,并能够告知每次调用何时完成 - 即使一个调用被延迟,所以long 它在稍后的调用后完成。这种硬编码的方法不再有效,原因有两个:

  1. 每次加载 something.js 都会调用相同的 loadJson() 回调 - 您无法知道哪个请求对应哪个回复。

  2. 缓存 - 一旦你加载了 something.js 一次,浏览器就不会再次请求服务器 - 它只会从缓存中取回它,破坏你的计划。

您可以通过告诉服务器每次以不同方式包装 JSON 来解决这两个问题,简单的方法是在查询字符串参数中传递该信息,例如 ?callback=loadJson12345。就好像您的页面看起来像这样:

<script>
function loadJson1(json) {
    // Read the json
}
function loadJson2(json) {
    // Read the json
}
</script>
<script src="//outsidedomain.com/something.js?callback=loadJson1"></script>
<script src="//outsidedomain.com/somethingelse.js?callback=loadJson2"></script>

使用 JQuery,这一切都被抽象化,让您看起来像对 $.ajax 的正常调用,这意味着您期待成功函数被触发。为了确保为每个 jsonp 加载触发正确的成功函数,JQuery 在全局命名空间中创建了一个长的随机回调函数名称,如 JQuery1233432432432432,将其作为查询字符串中的回调参数传递,然后等待脚本加载。如果一切正常,加载的脚本会调用 JQuery 请求的回调函数,这反过来会从 $.ajax 调用中触发成功处理程序。

请注意,“正常工作”要求服务器端读取 ?callback 查询字符串参数并将其包含在响应中,如 ?callback=joe -> joe({...。如果它是静态文件或服务器不以这种方式播放,您可能需要将该文件视为可缓存 - 见下文。

缓存

如果您想让 json 缓存,您可以通过设置 cache: true 并将 jsonpCallback 属性设置为硬编码到可缓存 json 文件中的字符串,让 JQuery 做一些更接近我的第一个示例的事情。例如这个静态 json:

loadJoe({name:'Joe'})

可以像这样在 JQuery 中加载和缓存:

$.ajax({
    url: '//outsidedomain.com/loadjoe.js',
    dataType: 'jsonp',
    cache: true,
    jsonpCallback: 'loadJoe',
    success: function(json) { ... }
});

关于javascript - jQuery 中的并行 JSONP 请求不会触发多个 "callback events"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10289501/

相关文章:

jquery - 在移动设备上实时更新 JQueryUI Tooltip 的内容

javascript - Android Webview 不会加载 HTML 的 Javascript 脚本

javascript - 我如何让 Geonames api 与 https 一起工作?

javascript - 如何访问我从客户端(NodeJs)发布的数据

javascript - 带自动相册的 Ajax 图片 uploader

javascript - 如何将 onclick() 和 href 都附加到 <a> 元素,但一次只能进行一项工作

javascript - 如何将 Angular 范围对象传递给新创建的 DOM

javascript - 离开页面后保持复选框处于选中状态

javascript - 如何使用 Grails Controller 中的 JSON 填充选择框

javascript - 使用 Javascript 更新复选框选择的输入字段