【问题标题】:Can anyone explain what JSONP is, in layman terms? [duplicate]谁能用外行术语解释 JSONP 是什么? [复制]
【发布时间】:2011-04-19 21:23:54
【问题描述】:

我知道JSONP 是带有填充的JSON

我了解 JSON 是什么,以及如何将它与 jQuery.getJSON() 一起使用。但是,在介绍 JSONP 时,我不明白callback 的概念。

谁能向我解释一下这是如何工作的?

【问题讨论】:

标签: jquery jsonp


【解决方案1】:

假设您有一些 URL 为您提供 JSON 数据,例如:

{'field': 'value'}

...你有一个类似的 URL,除了它使用 JSONP,你将回调函数名称“myCallback”传递给它(通常通过给它一个名为“callback”的查询参数来完成,例如http://example.com/dataSource?callback=myCallback)。然后它会返回:

myCallback({'field':'value'})

...这不仅仅是一个对象,而是实际上可以执行的代码。因此,如果您在页面的其他位置定义了一个名为 myFunction 的函数并执行此脚本,它将使用来自 URL 的数据调用。

这很酷的一点是:您可以创建一个脚本标签并使用您的 URL(带有callback 参数)作为src 属性,浏览器将运行它。这意味着您可以绕过“同源”安全策略(因为浏览器允许您从页面域以外的源运行脚本标签)。

这是 jQuery 在您发出 ajax 请求时所做的(使用 .ajax 和 'jsonp' 作为 dataType 属性的值)。例如

$.ajax({
  url: 'http://example.com/datasource',
  dataType: 'jsonp',
  success: function(data) {
    // your code to handle data here
  }
});

这里,jQuery 负责回调函数名称和查询参数 - 使 API 与其他 ajax 调用相同。但与其他类型的 ajax 请求不同,如前所述,您不限于从与您的页面相同的来源获取数据。

【讨论】:

  • 嗯,终于明白了;)
  • 终于有人知道如何传递信息了。谢谢@sje397
【解决方案2】:

前言:

这个答案已经超过六年了。虽然 JSONP 的概念和应用没有改变 (即答案的细节仍然有效),你应该 look to use CORS where possible (即您的serverAPI 支持它,并且 browser support 就足够了), 作为 JSONP has inherent security risks


JSONP(JSON with Padding)是一种常用的方法 绕过浏览器中的跨域策略。 (您不得向浏览器认为位于不同服务器上的网页发出 AJAX 请求。)

JSON 和 JSONP 在客户端和服务器上的行为不同。 JSONP 请求不使用XMLHTTPRequest 和相关的浏览器方法分派。而是创建了一个 <script> 标记,其源设置为目标 URL。然后将此脚本标记添加到 DOM(通常在 <head> 元素内)。

JSON 请求:

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {
  if (xhr.readyState == 4 && xhr.status == 200) {
    // success
  };
};

xhr.open("GET", "somewhere.php", true);
xhr.send();

JSONP 请求:

var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';

document.getElementsByTagName("head")[0].appendChild(tag);

JSON 响应和 JSONP 响应的区别在于 JSONP 响应对象作为参数传递给回调函数。

JSON:

{ "bar": "baz" }

JSONP:

foo( { "bar": "baz" } );

这就是为什么您会看到 JSONP 请求包含 callback 参数,以便服务器知道包装响应的函数的名称。

此函数必须存在在全局范围内当时浏览器评估<script>标签(一旦请求完成)。


在处理 JSON 响应和 JSONP 响应之间需要注意的另一个区别是,JSON 响应中的任何解析错误都可以通过包装评估 responseText 的尝试来捕获 在 try/catch 语句中。由于 JSONP 响应的性质,响应中的解析错误将导致无法捕获的 JavaScript 解析错误。

两种格式都可以通过在发起请求之前设置超时并在响应处理程序中清除超时来实现超时错误。


使用 jQuery

​​>

使用jQuery 发出 JSONP 请求的用处在于 jQuery 在后台为您完成所有工作

默认情况下,jQuery 要求您在 AJAX 请求的 URL 中包含 &callback=?。 jQuery 将获取您指定的success 函数,为其分配一个唯一的名称,并在全局范围内发布它。然后它将用它分配的名称替换&callback=? 中的问号?


可比较的 JSON/JSONP 实现

以下假设一个响应对象{ "bar" : "baz" }

JSON:

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {
  if (xhr.readyState == 4 && xhr.status == 200) {
    document.getElementById("output").innerHTML = eval('(' + this.responseText + ')').bar;
  };
};

xhr.open("GET", "somewhere.php", true);
xhr.send();

JSONP:

function foo(response) {
  document.getElementById("output").innerHTML = response.bar;
};

var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';

document.getElementsByTagName("head")[0].appendChild(tag);

【讨论】:

  • 这个解释属于博物馆!在解释 jsonp 的最佳工作上向 @Matt 提供所有支持。说真的,花了一整天的时间阅读东西,这是迄今为止最好的。
  • 优秀的外行解释。回复:“这就是为什么您看到 JSONP 请求包含“回调”参数的原因;因此服务器知道用于包装响应的函数的名称。” -- 我只是想补充一点,服务器甚至不必返回传递给回调函数的 JSON 对象 -- 它可以返回任意 JavaScript 代码(例如:jsontest.com/#code)。可能性是巨大的。
  • 本质上不仅可以从外部网络服务器请求data,现在foreign网络服务器可以注入any 自动将脚本写入网页,并且客户端没有能力甚至可以在代码执行之前查看代码!将JSON.parse 替换为eval 以获取安全性还有很长的路要走。
  • 我仍然不确定 JSONP 的意义何在。如果服务器确实可以添加填充,它也可以将 Access-Control-Allow-Origin 标头放在响应中?
  • @AndrewSavinykh:你是对的。但是,除了服务器添加“Access-Control-Allow-Origin”标头之外,您还需要have CORS support 的浏览器。 IE7 没有支持,IE8 和 9 在XMLHttpRequest 之外有支持(注意这个答案来自 2010 年!)。鉴于 Microsoft 不再支持这些浏览器,并且 JSONP 的安全隐患,应尽可能使用 CORS(如果可用)。
【解决方案3】:

JSONP 是一种绕过浏览器same-origin policy 的方法。如何?像这样:

这里的目标是向响应中的名称otherdomain.comalert 发出请求。通常我们会发出 AJAX 请求:

$.get('otherdomain.com', function (response) {
  var name = response.name;
  alert(name);
});

但是,由于请求将发送到不同的域,所以它不起作用。

不过,我们可以使用<script> 标签发出请求。 <script src="otherdomain.com"></script>$.get('otherdomain.com') 都会产生相同的请求:

GET otherdomain.com

问:但是如果我们使用<script> 标签,我们如何访问响应?如果我们想alert它,我们需要访问它。

A:呃,我们不能。但我们可以这样做 - 定义一个使用响应的函数,然后告诉服务器使用 JavaScript 响应,该 JavaScript 以响应作为参数调用我们的函数。

问:但是如果服务器不为我们做这件事,而只愿意返回 JSON 给我们呢?

A:那我们就不能用了。 JSONP需要服务器配合。

问:必须使用<script> 标签很难看。

答:像 jQuery make it nicer 这样的库。例如:

$.ajax({
    url: "http://otherdomain.com",
    jsonp: "callback",
    dataType: "jsonp",
    success: function( response ) {
        console.log( response );
    }
});

它通过动态创建 <script> 标签 DOM 元素来工作。

问:<script> 标签只发出 GET 请求 - 如果我们想发出 POST 请求怎么办?

A:那么 JSONP 对我们不起作用。

问:没关系,我只想发出一个 GET 请求。 JSONP 很棒,我会去使用它 - 谢谢!

A:实际上,它并没有那么棒。这真的只是一个黑客。和它isn't the safest 使用的东西。现在 CORS 可用,您应该尽可能使用它。

【讨论】:

  • 那个交互图帮了大忙,谢谢!
【解决方案4】:

我找到了一篇有用的文章,该文章也非常清楚和简单地解释了该主题。链接是JSONP

一些值得注意的点是:

  1. JSONP 早于 CORS。
  2. 这是一种从不同域检索数据的伪标准方式,
  3. CORS 功能有限(仅限 GET 方法)

工作如下:

  1. <script src="url?callback=function_name"> 包含在 html 代码中
  2. 当第 1 步被执行时,它会感知一个具有相同函数名称(在 url 参数中给出)的函数作为响应。
  3. 如果代码中存在具有给定名称的函数,则将使用作为该函数参数返回的数据(如果有)执行该函数。

【讨论】:

    猜你喜欢
    • 2012-01-30
    • 2015-08-23
    • 2015-07-06
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多