js便签笔记(13)——jsonp其实很简单【ajax跨域请求】

前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来。抱着有问题必须解决的态度,我看了许多资料,原来如此。。。

为何一直知道jsonp,但一直迷迷糊糊的不明白呢?——网上那些介绍资料都写的太复杂了!

我是能多简单就多简单,争取让你十分钟看完!

1. 同源策略

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

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

http://google.com  和  https://google.com 不同,因为协议不同;

http://localhost:8080  和  http://localhost:1000 不同,因为端口不同;

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

根据同源策略,我自己做的一个网页 http://localhost:8080/test.html 就无法通过ajax直接获取 http://google.com 的数据。

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

大家想想,这样其实也有道理。如果没有同源策略,你我都可以随便通过ajax直接获取其他网站的信息,这还不乱套了。。。我自己做一个搜索界面,搜索时直接用ajax从百度获取数据,那不成了小偷了。。。

但是跨域访问是少不了的,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 type='text/javascript' src='http://b.com/alert.js'/>
<script>
function myFn ( data ) {
alert( data + 'px' );
}
</script>

运行 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 type='text/javascript' src='http://b.com/data.html'/>
<script>
function myFn ( data ) {
alert( data + 'px' );
}
</script>

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

myFn(100); 

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

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

引导第五步:动态数据

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

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

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

大家注意,我们在 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);
} //需要调用时:
addScriptTag('b.com/data.aspx?callback=myFn'); function myFn (data) {
alert(data + 'px');
}

4. 总结

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

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

ok,就这些!

转载自:http://www.cnblogs.com/wangfupeng1988/p/4060747.html

jsonp其实很简单【ajax跨域请求】的更多相关文章

  1. 简单ajax跨域请求

    最近遇到需要ajax跨域的需求 首先看下不做任何处理特别处理的ajax跨域请求会出现什么样的错误 客户端代码: <script type="text/javascript"& ...

  2. 第114天:Ajax跨域请求解决方法(二)

    一.什么是跨域 我们先回顾一下域名地址的组成: http:// www . google : 8080 / script/jquery.js   http:// (协议号)       www  (子 ...

  3. 利用jsonp进行Ajax跨域请求

    在进行Ajax请求的时候经常会遇到跨域的问题,这个时候一般就会用到jsonp. 关于json和jsonp,网上有很多原理解释,这里就不多赘述,需要的自行搜索. 下面是一个简单的ajax跨域请求示例: ...

  4. JAVAEE——宜立方商城11:sso登录注册功能实现、通过token获得用户信息、Ajax跨域请求(jsonp)

    1. 学习计划 第十一天: 1.sso注册功能实现 2.sso登录功能实现 3.通过token获得用户信息 4.Ajax跨域请求(jsonp) 2. Sso系统工程搭建 需要创建一个sso服务工程,可 ...

  5. JSONP实现Ajax跨域请求

    前言 由于浏览器存在同源策略的机制,所谓同源策略就是阻止从一个源(域名,包括同一个根域名下的不同二级域名)加载的文档或者脚本获取/或者设置另一个源加载的文档属性. 但比较特别的是:由于同源策略是浏览器 ...

  6. 解决ajax跨域请求 (总结)

    ajax跨域请求,目前已用几种方法实现:   1)用原生js的xhr对象实现.                var url="http://freegeoip.net/json/" ...

  7. ASP.NET MVC 实现AJAX跨域请求方法《1》

    ASP.NET MVC 实现AJAX跨域请求的两种方法 通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据 ...

  8. jQuery ajax跨域请求的解决方法

    在Ajax应用中,jQuery的Ajax请求是非常容易而且方便的,但是初学者经常会犯一个错误,那就是Ajax请求的url不是本地或者同一个服务器下面的URI,最后导致虽然请求200,但是不会返回任何数 ...

  9. php中ajax跨域请求---小记

    php中ajax跨域请求---小记   前端时间,遇到的一个问题,情况大约是这样: 原来的写法: 前端js文件中: $.ajax({ type:'get', url:'http://wan.xxx.c ...

随机推荐

  1. MyEclipse 2014各种优化设置

    各种优化大整合,陆续更新使用中的问题,也欢迎大家提问. 1.通用优化设置:字体,UTF-8编码格式设置: http://jingyan.baidu.com/article/b907e627d2c5da ...

  2. JS小福利 —— 实时更新的页面小时钟

    今天小女刚学会了一个好玩的小玩意儿~~特来跟大家分享一下~~~ 这是一个有趣的时钟显示程序,可以进行实时的年月日.星期.时分秒更新,有了这组小代码,以后可以作为日期插件应用在大型的JS代码中哦~~ 积 ...

  3. Django视图,与数据库交互并返回数据

    环境:python 2.7.13  数据库:sqlite3(Django自带) 在学习Django的时候,遇到了困难.大概就是取到数据库数据后一直不能转成json数据.最后终于自己琢磨解决了. 要点就 ...

  4. 如何使用EF优雅的配置一对一的关系

    在这两天的时间已经有两位同事问到EF(Code First)如何配置一对一的关系,这个说难也不难,说简单吧,一旦设计跑偏那么在Coding的过程中将会很痛苦. 先举个很简单的例子,两个类User和Pr ...

  5. C# 获取exe、dll中的图标,支持获取256x256分辨率

    在网上找过许多文章,都没有成功获取过大图标,只能获取最大32x32.最后自己尝试了相关的windows api,终于找到一个可用的. 主要用到的C++的PrivateExtractIcons函数,具体 ...

  6. grunt之filerev、usemin

    窃以为这两个插件是比较有用的,filerev是给js.css进行编码重命名,usemin修改html中被重命名的js.css文件的引用.另外说明下之前将concat.cssmin.uglify放在一篇 ...

  7. RadioButtonList控件如何取得选中的值

    1.需求:我现在页面上有放两个单选控件,现在要通过判断不同的单选控件来对页面上的标签进行显示和隐藏操作 2.控件如下 <asp:RadioButtonList ID=" RepeatD ...

  8. HTTP请求响应机制与响应状态码

    转载来源:http://blog.csdn.net/xyw591238/article/details/51907143 HTTP协议 Internate的基本协议是TCP/IP(传输控制协议和网际协 ...

  9. 团队作业1——团队展示&博客作业查重系统

    团队展示: 1.队名:六个核桃 2.队员学号: 王婧(201421123065).柯怡芳(201421123067组长).陈艺菡(201421123068). 钱惠(201421123071).尼玛( ...

  10. 【Beta】 第二次Daily Scrum Meeting

    一.本次会议为第二次meeting会议 二.时间:13:30AM-13:55AM 地点:禹州 三.会议站立式照片 四.今日任务安排 成员 昨日任务 今日任务 林晓芳 对已完成的功能进行进一步测试,以便 ...