什么是 JSONP,为什么要创建它?

新手上路,请多包涵

我了解 JSON,但不了解 JSONP。 维基百科关于 JSON 的文档 是(曾经)JSONP 的最高搜索结果。它是这样说的:

JSONP 或“带填充的 JSON”是 JSON 扩展,其中前缀被指定为调用本身的输入参数。

嗯?什么电话?这对我来说没有任何意义。 JSON 是一种数据格式。没有电话。

第二个搜索结果 来自某个名叫 Remy 的人,他写了这个关于 JSONP 的内容:

JSONP 是脚本标签注入,将来自服务器的响应传递给用户指定的函数。

我可以理解这一点,但它仍然没有任何意义。


那么什么是 JSONP?为什么创建它(它解决了什么问题)?我为什么要使用它?


附录:我刚刚在 Wikipedia 上为 JSONP 创建了一个新页面;它现在根据 jvenema 的回答对 JSONP 进行了清晰而全面的描述。

原文由 Cheeso 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 586
2 个回答

其实也不是很复杂…

假设您在域 example.com 上,并且您想向域 example.net 发出请求。为此,您需要 跨越域 边界, 是大多数浏览器领域的禁忌。

绕过此限制的一项是 <script> 标签。当您使用脚本标签时,域限制被忽略,但在正常情况下,您无法对结果 任何事情,脚本只是被评估。

输入 JSONP 。当您向启用 JSONP 的服务器发出请求时,您会传递一个特殊参数,该参数会告诉服务器一些关于您的页面的信息。这样,服务器就能够以您的页面可以处理的方式很好地包装其响应。

例如,假设服务器需要一个名为 callback 的参数来启用其 JSONP 功能。那么您的请求将如下所示:

 http://www.example.net/sample.aspx?callback=mycallback

如果没有 JSONP,这可能会返回一些基本的 JavaScript 对象,如下所示:

 { foo: 'bar' }

然而,使用 JSONP,当服务器接收到“回调”参数时,它会稍微不同地包装结果,返回如下内容:

 mycallback({ foo: 'bar' });

如您所见,它现在将调用您指定的方法。因此,在您的页面中,您定义了回调函数:

 mycallback = function(data){
 alert(data.foo);
 };

现在,当脚本被加载时,它将被评估,并且你的函数将被执行。瞧,跨域请求!

还值得注意的是 JSONP 的一个主要问题:您失去了对请求的大量控制。例如,没有“好”的方式来获取正确的故障代码。结果,您最终使用计时器来监视请求等,这总是有点可疑。 JSONRequest 的提议是一个很好的解决方案,它允许跨域脚本、维护安全性和允许对请求进行适当的控制。

这些天(2015 年), CORS 是推荐的方法,而不是 JSONRequest。 JSONP 对于较旧的浏览器支持仍然有用,但考虑到安全隐患,除非您别无选择,否则 CORS 是更好的选择。

原文由 Jerod Venema 发布,翻译遵循 CC BY-SA 4.0 许可协议

JSONP 确实是一个克服 XMLHttpRequest 相同域策略的简单技巧。 (如您所知,不能将 AJAX (XMLHttpRequest) 请求发送到不同的域。)

所以 - 而不是使用 XMLHttpRequest 我们必须使用 脚本 HTML 标签,这些标签通常用于加载 js 文件,以便 js 从另一个域获取数据。听起来怪怪的?

事实是, 脚本 标签可以以类似于 XMLHttpRequest 的方式使用!看一下这个:

 script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';

加载数据后,您将得到一个如下所示的 脚本 段:

 <script>
{['some string 1', 'some data', 'whatever data']}
</script>

然而这有点不方便,因为我们必须从 脚本 标签中获取这个数组。所以 JSONP 的创建者决定这会更好地工作(而且确实如此):

 script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';

注意到那边的 my_callback 函数了吗?所以 - 当 JSONP 服务器收到您的请求并找到回调参数时 - 它不会返回普通的 js 数组,而是返回这个:

 my_callback({['some string 1', 'some data', 'whatever data']});

看看利润在哪里: 现在我们得到自动回调(my_callback),一旦我们获得数据就会触发。

这就是关于 JSONP 的全部信息:它是一个回调和脚本标签。

注意:这些是 JSONP 用法的简单示例,它们不是生产就绪的脚本。

基本 JavaScript 示例(使用 JSONP 的简单 Twitter 提要)

 <html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text = '';
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

基本 jQuery 示例(使用 JSONP 的简单 Twitter 提要)

 <html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text = '';
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>

JSONP 代表 带填充的 JSON 。 (这个技术命名很差,因为它实际上与大多数人认为的“填充”毫无关系。)

原文由 ThatGuy 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题