自己封装的JSONP跨域函数


前几天遇到这样一个题目。

JSONP(url, {
  data: {
    key1: value1
  },
  callback: function (data) {
    // data 是服务端返回的数据
  }
})

实现可发送 JSONP 请求、获取 JSONP 返回结果的函数:

尝试封装了一个JSONP的函数。用来进行跨域操作。调用方式类似jQuery的ajax方式。


主要实现功能:

1.参数拼装。

2.给每个回调函数唯一命名。

3.在回调成功或请求失败之后删除创建的javascript标签。 需要兼容IE。IE下onerror事件不兼容。这里有对它的模拟实现。在IE下加载失败也能get到。

4.超时功能。超时取消回调。执行error。

5.error事件。可执行自己传入的error事件。

代码封装,调用,以及后台代码如下

jsonp.js
/*author:ls <841766635@qq.com>
* data:2016/03/20
*/

function JSONP(url,config){
	var data = config.data || [];
	var paraArr=[],paraString='';//get请求的参数。
	var urlArr;
	var callbackName;//每个回调函数一个名字。按时间戳。
	var script,head;//要生成script标签。head标签。
	var supportLoad;//是否支持 onload。是针对IE的兼容处理。
	var onEvent;//onload或onreadystatechange事件。
	var timeout = config.timeout || 0;//超时功能。

	for(var i in data){
		if(data.hasOwnProperty(i)){
			paraArr.push(encodeURIComponent(i) + "=" +encodeURIComponent(data[i]));
		}
	}

	urlArr = url.split("?");//链接中原有的参数。
	if(urlArr.length>1){
		paraArr.push(urlArr[1]);
	}

	callbackName = 'callback'+new Date().getTime();
	paraArr.push('callback='+callbackName);
	paraString = paraArr.join("&");
	url = urlArr[0] + "?"+ paraString;

	script = document.createElement("script");
	script.loaded = false;//为了实现IE下的onerror做的处理。JSONP的回调函数总是在script的onload事件(IE为onreadystatechange)之前就被调用了。因此我们在正向回调执行之时,为script标签添加一个属性,然后待到onload发生时,再检测有没有这个属性就可以判定是否请求成功,没有成功当然就调用我们的error。

	//将回调函数添加到全局。
	window[callbackName] = function(arg){
		var callback = config.callback;
		callback(arg);
		script.loaded = true;
	}

	head = document.getElementsByTagName("head")[0];
	head.insertBefore(script, head.firstChild) //chrome下第二个参数不能为null
	script.src = url;

	supportLoad = "onload" in script;
	onEvent = supportLoad ? "onload" : "onreadystatechange";

	script[onEvent] = function(){

		if(script.readyState && script.readyState !="loaded"){
			return;
		}
		if(script.readyState == 'loaded' && script.loaded == false){
			script.onerror();
			return;
		}
		//删除节点。
		(script.parentNode && script.parentNode.removeChild(script))&& (head.removeNode && head.removeNode(this));	
		script = script[onEvent] = script.onerror = window[callbackName] = null;

	}

	script.onerror = function(){
		if(window[callbackName] == null){
			console.log("请求超时,请重试!");
		}
		config.error && config.error();//如果有专门的error方法的话,就调用。
		(script.parentNode && script.parentNode.removeChild(script))&& (head.removeNode && head.removeNode(this));	
		script = script[onEvent] = script.onerror = window[callbackName] = null;
	}

	if(timeout!= 0){
		setTimeout(function() {
			if(script && script.loaded == false){
				window[callbackName] = null;//超时,且未加载结束,注销函数
				script.onerror();				
			}
		}, timeout);
	}

}

jsonp.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>jsonp测试</title>
	<script src="jsonp.js"></script>
</head>
<body>
	<script>
		function myerror(){
			alert('there must be something wrong!');
		}
		function getData (data){
			alert("服务器过来的数据是"+data);
		}
		var url = 'http://runningls.com/demos/2016/jsonp/jsonp.php';
		//调用函数。
		JSONP(url,{
			data:{
				id:1
			},
			callback:getData,
			error:myerror,
			timeout:10000
		});
	</script>
</body>

jsonp.php
<?php 

$callback = $_GET['callback'];
$id = $_GET['id'];

if($id == 1){
	$res = 'this is 1';
}

if($id == 2){
	$res = 'this is 2';
}

$res = $callback."('$res')";

echo $res;

?>


演示地址: http://runningls.com/demos/2016/jsonp/jsonp.html


参考文章:http://www.cnblogs.com/rubylouvre/p/4277408.html

http://www.cnblogs.com/rubylouvre/archive/2011/02/13/1953087.html


转载请注明出处:http://blog.csdn.net/liusaint1992/article/details/50959571

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值