在web2.0时代,熟练的使用ajax是每个前端攻城师必备的技能。然而由于受到浏览器的限制,ajax不允许跨域通信。

JSONP就是就是目前主流的实现跨域通信的解决方案。

虽然在在jquery中,我们可以通过$.ajax的dataType设置为jsonp来调用jsonp,但是jsonp和ajax的实现原理一个关系都木有。jsonp主要是通过script可以链接远程url来实现跨域请求的。如:

<script src="http://jsonp.js?callback=xxx"></script>

callback定义了一个函数名,而远程服务端通过调用指定的函数并传入参数来实现传递参数。

搜索了网上好多文章,他们实现方法都过于简单,要实际应用还要多加修改,我在这里封装了一个对象,可以直接运用于实际操作。

var JSONP = {
// 获取当前时间戳
now: function() {
return (new Date()).getTime();
}, // 获取16位随机数
rand: function() {
return Math.random().toString().substr(2);
}, // 删除节点元素
removeElem: function(elem) {
var parent = elem.parentNode;
if(parent && parent.nodeType !== 11) {
parent.removeChild(elem);
}
}, // url组装
parseData: function(data) {
var ret = "";
if(typeof data === "string") {
ret = data;
}
else if(typeof data === "object") {
for(var key in data) {
ret += "&" + key + "=" + encodeURIComponent(data[key]);
}
}
// 加个时间戳,防止缓存
ret += "&_time=" + this.now();
ret = ret.substr(1);
return ret;
}, getJSON: function(url, data, func) {
// 函数名称
var name; // 拼装url
url = url + (url.indexOf("?") === -1 ? "?" : "&") + this.parseData(data); // 检测callback的函数名是否已经定义
var match = /callback=(\w+)/.exec(url);
if(match && match[1]) {
name = match[1];
} else {
// 如果未定义函数名的话随机成一个函数名
// 随机生成的函数名通过时间戳拼16位随机数的方式,重名的概率基本为0
// 如:jsonp_1355750852040_8260732076596469
name = "jsonp_" + this.now() + '_' + this.rand();
// 把callback中的?替换成函数名
url = url.replace("callback=?", "callback="+name);
// 处理?被encode的情况
url = url.replace("callback=%3F", "callback="+name);
} // 创建一个script元素
var script = document.createElement("script");
script.type = "text/javascript";
// 设置要远程的url
script.src = url;
// 设置id,为了后面可以删除这个元素
script.id = "id_" + name; // 把传进来的函数重新组装,并把它设置为全局函数,远程就是调用这个函数
window[name] = function(json) {
// 执行这个函数后,要销毁这个函数
window[name] = undefined;
// 获取这个script的元素
var elem = document.getElementById("id_" + name);
// 删除head里面插入的script,这三步都是为了不影响污染整个DOM啊
JSONP.removeElem(elem);
// 执行传入的的函数
func(json);
}; // 在head里面插入script元素
var head = document.getElementsByTagName("head");
if(head && head[0]) {
head[0].appendChild(script);
}
}
};

实现过程基本写在注释里啦,自己看。调用的方法跟jQuery基本一样。如:

var data = {
from: "北京",
count: 27,
output: "json",
callback: "?"
}
JSONP.getJSON("http://api.qunar.com/cdnWebservices.jcp", data, function(json) {console.log(json)});

当然要这么写也行:

JSONP.getJSON("http://api.qunar.com/cdnWebservices.jcp?from=北京&count=27&output=json&callback=?", null, function(json) {console.log(json)});

至于服务端的实现,那就比较简单了,以php为例:

$callback = !empty($_GET['callback']) ? $_GET['callback'] : 'callback';
echo $callback.'( .json_encode( $data ).')';

跨域通信的解决方案JSONP的更多相关文章

  1. 黄聪:利用iframe实现ajax 跨域通信的解决方案(转)

    原文:http://www.cnblogs.com/xueming/archive/2013/02/01/crossdomainajax.html 在漫长的前端开发旅途上,无可避免的会接触到ajax, ...

  2. 使用 JSONP 实现跨域通信

    简介 Asynchronous JavaScript and XML (Ajax) 是驱动新一代 Web 站点(流行术语为 Web 2.0 站点)的关键技术.Ajax 允许在不干扰 Web 应用程序的 ...

  3. 使用JSONP实现跨域通信

    引语 Ajax 允许在不干扰 Web 应用程序的显示和行为的情况下在后台进行数据检索.Ajax 允许在不干扰 Web 应用程序的显示和行为的情况下在后台进行数据检索.由于受到浏览器的限制,该方法不允许 ...

  4. 跨域问题,解决方案-Nginx反向代理

    跨域问题,解决之道 跨域问题,在日常开发过程中,是一个非常熟悉的名词.今天的话题,结合我之前的项目场景,讨论下<跨域问题,解决之道>. 跨域是什么 跨域问题,是由于JavaScript出于 ...

  5. ajax跨域原理以及解决方案

    说明 跨域主要是由于浏览器的“同源策略”引起,分为多种类型,本文主要探讨Ajax请求跨域问题 前言 强烈推荐阅读参考来源中的文章,能够快速帮助了解跨域的原理 参考来源 本文参考了以下来源 浏览器同源政 ...

  6. JavaScript 跨域:window.postMessage 实现跨域通信

    JavaScript 跨域方式实现方式有很多,之前,一篇文章中提到了 JSONP 形式实现跨域.本文将介绍 HTML5 新增的 api 实现跨域:window.postMessage . 1 othe ...

  7. 【JavsScript】父子页面之间跨域通信的方法

    由于同源策略的限制,JavaScript跨域的问题,一直是一个比较棘手的问题,为了解决页面之间的跨域通信,大家煞费苦心,研究了各种跨域方案.之前也有小网同学分享过一篇“跨域,不再纠结” 开始照着尝试时 ...

  8. 【JavaScript】父子页面之间跨域通信的方法

    由于同源策略的限制,JavaScript跨域的问题,一直是一个比较棘手的问题,为了解决页面之间的跨域通信,大家煞费苦心,研究了各种跨域方案.之前也有小网同学分享过一篇“跨域,不再纠结” 开始照着尝试时 ...

  9. 使用window.postMessage实现跨域通信

    JavaScript由于同源策略的限制,跨域通信一直是棘手的问题.当然解决方案也有很多: document.domain+iframe的设置,应用于主域相同而子域不同: 利用iframe和locati ...

随机推荐

  1. selenium,unittest——下拉菜单操作,百度账号设置修改

    #encoding=utf-8from selenium import webdriverimport time,unittest, re,sysfrom HTMLTestRunner import ...

  2. python-property、__get__、__set__

    目录 property __set__ 和 __get__ property property装饰器的应用来自这样一个问题:如果对实例的属性值不加以限制,那么实例的属性值会出现明显不合理的情况,为了解 ...

  3. Laxcus大数据操作系统单机集群版

    Laxcus大数据管理系统是我们Laxcus大数据实验室历时5年,全体系全功能设计研发的大数据产品,目前的最新版本是2.1版本.从三年前的1.0版本开始,Laxcus大数据系统投入到多个大数据和云计算 ...

  4. ecshop以及一些需要注意的

    Deprecated: Assigning the return value of new by reference is deprecated in 定位到出错的那一行: $this->_ol ...

  5. socket编程 123

    1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情,大概大家都把它定位在脚本语言的范畴内吧,但是其实php的socket模块可以做很多事情,包括做ftplist,http ...

  6. CSS中水平居中设置的几种方式

    1.行内元素: 如果被设置元素为文本.图片等行内元素时,水平居中是通过给父元素设置 text-align:center 来实现的. <body> <div class="t ...

  7. c# 加载图片 正在被占用问题

    问题情境:图片文件加载到pdf中,程序没有退出,再次加载该图片文件,提示被占用. 解决办法: 1.加载文件会锁定该文件,fromfile方法会导致占用内存较大,不使用该方法. FileStream f ...

  8. lintcode-477-被围绕的区域

    477-被围绕的区域 给一个二维的矩阵,包含 'X' 和 'O', 找到所有被 'X' 围绕的区域,并用 'X' 填充满. 样例 给出二维矩阵: X X X X X O O X X X O X X O ...

  9. vsftpd 安全性能工具

    vsftpd实战(服务端192.168.23.12,客户端192.168.23.11) 1:安装vsftpdyum install -y vsftpd 2:客户端安装lftpyum install - ...

  10. SpringCloud——服务网关

    1.背景 上篇博客<SpringCloud--Eureka服务注册和发现>中介绍了注册中心Eureka.服务提供者和服务消费者.这篇博客我们将介绍服务网关. 图(1) 未使用服务网关的做法 ...