Javascript 对JSONP请求如何工作感到困惑

Javascript 对JSONP请求如何工作感到困惑,javascript,ajax,jsonp,Javascript,Ajax,Jsonp,我很难理解jsonp请求如何工作的细节。我已经阅读了包括jsonp上的wiki在内的多个源代码,但对于回调函数在进行jsonp调用时如何实际获取从服务器返回的函数,我仍然非常困惑。例如,在wiki中,请求的源设置为: src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse" jsonp=parseResponse究竟是什么意思??然后他们继续说有效载荷是: parseResponse({"

我很难理解jsonp请求如何工作的细节。我已经阅读了包括jsonp上的wiki在内的多个源代码,但对于回调函数在进行jsonp调用时如何实际获取从服务器返回的函数,我仍然非常困惑。例如,在wiki中,请求的源设置为:

src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse"
jsonp=parseResponse究竟是什么意思??然后他们继续说有效载荷是:

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});

这是怎么回事?我对整个回调功能感到困惑。函数名parseResponse被传递到服务器,返回的数据以某种方式成为该函数的参数?有人能确切地解释一下如何从jsonp请求中检索/使用数据吗?

编辑:正如Jon所说,有一种更好的解释方法

JSONP使用脚本标记进行跨源请求。由于脚本标记用于包含脚本,服务器需要返回有效的JavaScript。我们向客户机提供JavaScript的方式是通过函数调用。告诉服务器希望脚本调用什么函数,然后在本地创建该函数。加载脚本后,将调用函数,并将数据作为参数

因此,如果您在您提到的URL上执行了一个JSONP请求,并且它返回了您提到的负载,那么您可以通过执行以下操作来获取数据:

function parseResponse(data) {
    console.log("JSONP request complete", data);
}
函数名parseResponse被传递到服务器,并以某种方式 返回的数据将成为此函数的参数

看起来就像你自己解释的,
jsonp=parseResponse
是这个应用程序设置回调函数的方式,所以它返回一个包含json数据的函数,看起来像

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});
它在加载时被调用,并由JS中的函数处理,如:

function parseResponse(data){
    console.log(data);
}

回调函数是您在自己的代码中定义的函数。jsonp服务器将使用一个名为与指定回调函数相同的函数调用包装其响应

这种情况下会发生什么:

1) 您的代码创建JSONP请求,这将导致一个新的
块,如下所示:

<script src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse"></script>
3) 因为这个请求来自一个脚本标记,所以它与您实际放置的脚本标记几乎完全相同

<script>
    parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});
</script>
基本上,JSONP是一种绕过浏览器的同源脚本安全策略的方法,通过让第三方服务器将函数调用直接注入到页面中。注意,这在设计上是非常不安全的。您需要确保远程服务是值得尊敬的,并且没有恶意。没有什么能阻止一个糟糕的服务返回一些窃取你银行/facebook/任何凭证的JS代码。e、 JSONP的反应可能是

 internalUseOnlyFunction('deleteHarddrive');

而不是ParseResponse(…)。如果远程站点知道您的代码结构,它可以使用该代码执行任意操作,因为你已经打开了你的前门,允许该站点做它想做的任何事情。

返回的数据如何神奇地成为parseRepsonse函数的参数的可能重复?@JohnBaum,因为服务器创建了将被调用的JS代码?我不会像
deleteHardDrive
(javascript无法从浏览器中实现这一点)但值得注意的是,这可能会很危险。
function parseResponse(data) {
     alert(data.Name); // outputs 'Foo'
}
 internalUseOnlyFunction('deleteHarddrive');