ajax跨域请求-jsonp

1. 同源策略

ajax之因此须要“跨域”,罪魁祸首就是浏览器的同源策略。即,一个页面的ajax只能获取这个页面相同源或者相同域的数据。javascript

如何叫“同源”或者“同域”呢?——协议、域名、端口号都必须相同。例如:css

http://google.com  和  https://google.com 不一样,由于协议不一样;html

http://localhost:8080  和  http://localhost:1000 不一样,由于端口不一样;前端

http://localhost:8080  和  https://google.com 不一样,协议、域名、端口号都不一样,根本不是一家的。java

根据同源策略,我本身作的一个网页 http://localhost:8080/test.html 就没法经过ajax直接获取 http://google.com 的数据。ajax

例如,我用ajax去访问一个不一样域的页面,错误结果是这样的:编程

技术分享

 

你们想一想,这样其实也有道理。若是没有同源策略,你我均可以随便经过ajax直接获取其余网站的信息,这还不乱套了。。。我本身作一个搜索界面,搜索时直接用ajax从百度获取数据,那不成了小偷了。。。json

可是跨域访问是少不了的,mail.163.com 的网页可能须要从 news.163.com 域下获取新闻信息,那怎么办?——开始我们的跨域之旅。(固然用iframe也能够实现)跨域

2. 从“盗链”提及

互联网的许多网站之间图片相互盗链,A网站网页的img.src直接连接到B网站的图片地址,这是常有的事儿。说到“盗链”,你们第一想到的多是如何去防止盗链,今儿咱无论那个。浏览器

你再想一想“盗链”和“同源策略”这两个词之间有什么关系?——对,矛盾!既然都“同源策略”了,怎么还能“盗链”呢?

世间万物都有矛盾,有矛盾了照样能够和谐共处,并不必定非要你死我活。

重点:<img>的src(获取图片),<link>的href(获取css),<script>的src(获取javascript)这三个都不符合同源策略,它们能够跨域获取数据。所以,你能够直接从一些cdn上获取jQuery,而且你网站上的图片也随时可能被别人盗用,全部最好加上水印!

而咱们今天的主角——jsonp——就是由于<script>的src不符合同源策略而来的。

3. JSONP

例如,域名 a.com 下有一个 a.com/test.html 网页,域名 b.com 下有一个 b.com/data.html 网页和 b.com/alert.js 文件。

引导第一步:简单引用js

编写 b.com/alert.js 以下:

alert(123);

对 a.com/test.html 编写以下代码:

<script type=‘text/javascript‘ src=‘http://b.com/alert.js‘/>

运行 a.com/test.html,结果很明显,就是弹出 【123】 。

 

引导第二步:引用js返回数据

将 b.com/alert.js 修改成:

myFn(100);

将 a.com/test.html 修改成:

<script>
    function myFn ( data ) {
        alert( data + ‘px‘ );
    }
</script>
<script type=‘text/javascript‘ src=‘http://b.com/alert.js‘/>

运行 a.com/test.html,结果是弹出【 100px 】,这个应该也没有什么疑问。

 

引导第三步:已经跨域成功!

第二步中,若是data——即100——是我要跨域在b.com下获取的一个数据,那么我们这不就是已经实现跨域请求了吗!!!

把这个过程再清晰的捋一遍:

  • <script>的src不符合同源策略;
  • 我经过给<script>的src赋值一个跨域的文件的网址(可能不是一个js文件),这个文件返回的字符串,浏览器会看成javascript来解析;
  • 而这段javascript中,就能够包含着我所须要的跨域服务器端的数据;
  • 最后,我在本页面定义一个myFn函数用来展现数据,而这段javascript中就能够直接调用myFn函数;

 

引导第四步:引用html格式

<script>的src不必定仅仅指向javascript文件,能够指向任何地址。例如:

将 a.com/test.html 修改成:

<script>
    function myFn ( data ) {
        alert( data + ‘px‘ );
    }
</script>
<script type=‘text/javascript‘ src=‘http://b.com/data.html‘/>

将 b.com/data.html 编写为:(注意,data.html中就写如下一行代码,多了不写)

myFn(100); 

运行 a.com/test.html ,结果依然是【 100px 】

其中,“100”就是咱们要跨域请求的数据。

 

引导第五步:动态数据

若是要请求的数据是动态的,那就要在动态页面中编写。

那么咱们就让 a.com/test.html 去调用一个动态的aspx页面:

<script>
    function myFn ( data ) {
        alert( data + ‘px‘ );
    }
</script>
<script type=‘text/javascript‘ src=‘http://b.com/data.aspx?callback=myFn‘/>

你们注意,咱们在 src 地址中增长了“?callback=myFn”,意思是把显示数据的函数也动态传过去了,而第二步、第四步都是静态的写在被调用的文件中的。

至于callback参数后台如何接收,如何使用,请接着看:

在 b.com 下增长一个 b.com/data.aspx 页面,后台代码以下:

 
    protected void Page_Load(object sender, EventArgs e)
    {
        if (this.IsPostBack == false)
        {
            string callback = "";
            if (Request["callback"] != null)
            {
                callback = Request["callback"];

                //服务器端要返回的数据
                string data = "1024";

                Response.Write(callback + "(" + data + ")");
            }
        }
    }
 

代码很简单,获取callback参数,而后组成一个函数的形式返回。若是“b.com/data.aspx?callback=myFn”调用的话,那么返回的就是" myFn(1024) "。

返回的数据变成动态的了(“1024”),前端页面用于显示数据的函数也编程了动态的了(“callback=myFn”),可是归根结底,形式仍是同样的。

 

引导第六步:调用封装

a.com/test.html 中,仅仅有一个<script>静静的躺在那里,执行一次以后,就没有做用了。

而实际状况是,a.com/test.html 中,可能随着用户的操做发生若干次的调用。怎么办?——动态增长呗。

 
function addScriptTag(src) {
    var script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.src = src;
    document.body.appendChild(script);
}

function myFn (data) {
    alert(data + ‘px‘);  
}

//须要调用时:
//addScriptTag(‘b.com/data.aspx?callback=myFn‘);
 

 

4. 总结

以上层层描述的就是JSONP,你没必要去记住它的定义,看明白了上述文字,就全能理解。

重点在于:同源策略 + <script>的src不属于同源策略 + 经过<script>的src指向的文件返回服务器端数据。

ok,就这些!

相关文章
相关标签/搜索