码迷,mamicode.com
首页 > Web开发 > 详细

AJAX(六)jsonp原理详解

时间:2018-06-27 19:30:15      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:test   logs   tpc   来源   http   hello   了解   没有   开始   

  一、什么是jsonp?

  先别管什么叫jsonp,我们先来看一个小问题,看完这个问题你就知道jsonp是要解决什么问题的,自然也就明白什么是jsonp了。

  问题:

  之前做的例子如果在同一个域名下运行时是非常正常的,但如果这个数据接口是在A域名下,而使用了AJAX请求的静态页运行在B域名下,我们就会发现点击按钮发出请求时会报错。截个图来看看。

  技术分享图片

  我们看到后台的一般处理程序运行的域名是 : http://localhost:64113 

  现在使用VS重新创建1个web项目,然后在这个使用AJAX方式发出请求的静态页拷贝到这个新项目中。当然,这时候异步请求的请求url我们需要写成  http://localhost:64113/getTimeHandler.ashx。运行之,我们再来看截图:

  技术分享图片

  猛一看都是localhost,不过仔细看端口号,就可以知道了,现在是运行在不同域名下的2个完全独立的应用程序。如果这个时候点击按钮获取时间,我们在浏览器的控制台中就会看到报错。截图如下:

技术分享图片

  更极端的情况再试一试。我们这次仍然启动域名为http://localhost:64113 的服务,然后在文件系统下直接打开静态页HtmlPage.html,这时在浏览器的地址栏中看到的url是这样的:

  技术分享图片

  此时点击“获取时间”按钮,使用AJAX发出请求,在控制台中会报出同样的错误。

  这个错误不是代码写错了,如果我们的静态页发出的AJAX请求,所请求的目标跟当前页面是同一个域名,代码没有任何问题。

  这个错误是因为跨域引起的,简单的说,就是如果使用AJAX发出http请求,是不允许跨域的。说白了就是不允许你自己的网站,使用AJAX直接请求其他网站的服务。

  这是硬性规定。

  之所以有这种规定,原因是为了网络的安全。如果想了解到底安全问题会出在哪里,原理是如何的,请参考:浅谈CSRF攻击方式

   是时候给jsonp下个定义了。首先,jsonp不是json,json只是一种数据描述格式;jsonp只是用来解决AJAX不能跨域问题的一种手段,只不过在这种手段经常会用到json格式的数据,我想着可能就是jsonp名字的来源。

  如果你还不明白什么是jsonp,不知道为啥要跨域,那么咱们看这个例子。比如你要开发一个非常NB的网站,这个网站上要有天气预报的信息,你总不能自己建个气象站来观测气象得到天气数据吧,通常的做法是访问其他平台为我们提供的数据服务,那么很显然我们自己的网站是不可能跟那些专业提供数据服务的网站的域名是相同的,如果你使用AJAX的方式直接发出请求,这时候,对于提供数据服务的平台来说,你的http请求就是跨域的,这是非法的。

  但是为了完成项目需求我必须要访问,而且这些提供数据服务的平台就是让用户访问的,如何解决之呢?这时候就要是用jsonp的手段,简而言之,jsonp就是当使用异步的方式发出跨域http请求时,为了避开跨域访问限制的一种技术手段。这种技术手段并不复杂,只不过是拐了个弯而已。接下来我们就通过实例来一窥jsonp的究竟。

  二、jsonp原理

  (1)我不打算直接拿使用jsonp的代码来给大家看,请先从一个最基本的JavaScript的小例子开始,然后一步一步进化到jsonp的形式,我觉得这样更有助于大家理解。

  首先我们创建一个html文档,myPage.html,然后在该html文档中写入以下js代码。  

<script>
    function callback(data) {
        console.log(data);
    }
    callback("hello");
</script>

 

  此代码非常简单,声明了一个函数叫callback,然后调用它。在浏览器中打开这个页面,控制台会输出hello字符串。

  (2)改造这个案例,callback函数仍然在当前网页中声明,但是把callback("hello")这条调用的语句剪切走,我们另外创建一个单独的js文件,比如叫做test.js,这个文件中就一条js语句:callback("hello")。然后我们在myPage.html页面中引用这个外部的js脚本文件。代码如下:

<script>
    function callback(data) {
        console.log(data);
    }    
</script>
<script src="test.js"></script>

  这个页面打开以后,在浏览器控制台中一样可以看到hello字符串。这说明callback仍然被调用了。只不过调用callback的语句是写在外部文件test.js中的。  

  注意看红色的代码,这个script标签引用了一个外部文件,当浏览器解释到这行html代码时,就会去请求这个外部的js脚本文件,并且把这个文件加载进来,运行该js脚本内的所有JavaScript代码。而这个外部的test.js文件又恰好只有一条语句:callback(“hello”);就是调用上一个script标签中声明的函数。于是该函数就被执行1次,于是我们就看到了控制台中输出hello字符串。

  技术分享图片

  额,题是没跑的。这里要说明的是,在JavaScript中,可以在A文件中声明一个函数,而在另外一个文件B中去调用它。

  而接下来要说的jsonp的基本实现原理就是基于下面2个事实。

  1. 不允许直接在AJAX发出跨域请求,但是,允许<script>标签的src属性引用一个跨域的资源。
  2. 在JavaScript中,可以在A文件中声明一个函数,而在另外一个文件B中去调用它

  (3)再次用获取服务器时间的例子。如果之前的服务端代码如果忘了,可以再去看看AJAX(一)初识AJAX 。我们这次要是用jsonp的方式,让这个服务能够被跨域请求。

  先看服务端代码,我们改造为:

public class getTimeHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        string nowTime = DateTime.Now.ToLongTimeString();
        context.Response.Write("callback(‘" + nowTime + "‘);");
    }
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

 

  这个PR方法特殊之处就是不再直接返回时间字符串,而是返回了一个拼接的字符串,该字符串形如:“callback( ‘20:18:30‘)’”。

  再来看浏览器端的js代码:

<head>
    <title></title>
    <script>
        function callback(data) {
            console.log(data);
        }
    </script>
    <script src="http://localhost:64113/getTimeHandler.ashx"></script>
</head>

  这里通过一个<script>标签的src属性,去请求一个跨域的资源。而且得到的这个资源就是我们上边的服务端代码返回的字符串:callback( ‘20:18:30‘),正好是对本页面上声明的函数callback的调用。所以,这个页面打开后,我们就能在浏览器的控制台中看到输出的服务器时间。

  这就是jsonp的实现原理:

  1.不要直接使用AJAX去请求跨域的资源,而是把这个跨域的请求交给一个<script>标签来做。

  2.客户端要声明一个函数,用来处理服务端返回的数据。

  3.服务端不能仅仅返回客户端要展示的数据,而且要把数据跟js端声明的方法,两者按照js语法,品写成1个js函数调用的格式的大字符串。

  原理就是这么简单。接下来的一期,我会用一个案例来实现一个完整,使用原生的代码的,jsonp跨域请求。

 

AJAX(六)jsonp原理详解

标签:test   logs   tpc   来源   http   hello   了解   没有   开始   

原文地址:https://www.cnblogs.com/ldq678/p/9235625.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!