原生JS封装Ajax插件(同域、jsonp跨域)


Posted in Javascript onMay 03, 2016

抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢?

最近都在做原生JS熟悉的练习。。。

用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的。。。简单说说思路,如有不正确的地方,还望指正^_^

一、Ajax核心,创建XHR对象

Ajax技术的核心是XMLHttpRequest对象(简称XHR),IE5是第一款引入XHR对象的浏览器,而IE5中的XHR对象是通过MSXML库中的一个ActiveX对象实现的,因此在IE中可能有3个版本,即MSXML2.XMLHttp、MSXML2.XMLHttp.3.0和MSXML2.XMLHttp.6.0。所以创建XHR对象的时候要用兼容性写法:

createXHR:function(){
 if(typeof XMLHttpRequest!='undefined'){
 return new XMLHttpRequest();
 }else if(typeof ActiveXObject!='undefined'){
 if(typeof arguments.callee.activeXString!='string'){
 var versions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i,len;
 for(i=0,len=versions.length;i<len;i++){
 try{
  new ActiveXObject(versions[i]);
  arguments.callee.activeXString=versions[i];
  break;
 }catch(ex){
 }
 }
 return new ActiveXObject(arguments.callee.activeXString);
 }else{
 throw new Error("No XHR object available.");
 }
}

二、XHR的主要方法属性

方法:

open()方法:接受3个参数,要发送的请求的类型、请求的URL、是否异步发送的布尔值

send()方法:要作为请求主体发送的数据,如果不需要通过请求主体发送数据,则必须传入null

abort()方法:在接收到响应之前调用来取消异步请求。

属性:

responseText:作为响应主体被返回的文本。

status:响应的HTTP状态

statusText:HTTP状态说明

readyState:表示请求/响应过程的当前活动阶段

取值分别为:

0:未初始化。尚未调用open()方法

1:启动。已经调用open()方法,但尚未调用send()方法

2:发送。已经调用send()方法,但未接收到响应。

3:接收。已经接受到部分响应数据

4:完成。已经接受到全部响应数据,而且已经可以在客户端使用了。

本例中的onreadystatechange事件处理函数:

var complete=function(){
 if(xhr.readyState==4){
 if((xhr.status>=200&&xhr.status<300)||xhr.status==304){
 if(params.success){
  params.success(xhr.responseText);//执行调用ajax时指定的success函数
  }
 }else{
 if(params.fail){
 params.fail();//执行调用ajax时指定的fail函数
 }else{
 throw new Error("Request was unsucessful:"+xhr.status);
 }
 }
 }
}

注意:必须在调用open()方法之前指定onreadystatechange事件处理函数才能确保跨浏览器兼容性。

三、同域发送请求

①GET请求

最常见的请求类型,常用于查询某些信息。通过将查询的字符串参数追加到URL的末尾来将信息发送给服务器。get方法请求需要注意的是,查询字符串中的每个参数名称和值都必须使用encodeURIComponent()进行编码,而且所有名-值对都必须由&号分割。

请求方法:

if((this.config.type=="GET")||(this.config.type=="get")){
 for(var item in this.config.data){
 this.config.url=addURLParam(this.config.url,item,this.config.data[item]);//使用encodeURIComponent()进行编码
 }
 xhr.onreadystatechange=complete;
 xhr.open(this.config.type,this.config.url,this.config.async);
 xhr.send(null);
}

②POST请求

通常用于向服务器发送应该被保存的数据,POST请求应该把数据作为请求的主体提交。这里将模仿表单提交。即将Content-Type头部信息设置为application/x-www-form-urlencoded; charset=UTF-8。

序列化函数:

function serialize(data){
 var val="";
 var str="";
 for(var item in data){
  str=item+"="+data[item];
  val+=str+'&';
 }
 return val.slice(0,val.length-1);
 }

请求方法:

if(this.config.type=="POST"||this.config.type=="post"){
 xhr.addEventListener('readystatechange',complete);
 xhr.open(this.config.type,this.config.url,this.config.async);
 if(params.contentType){
  this.config.contentType=params.contentType;
  }
 xhr.setRequestHeader("Content-Type",this.config.contentType);
 xhr.send(serialize(this.config.data));
}

两个请求的一些区别:

 ①GET请求把参数数据写到URL中,在URL中可以看到,而POST看不到,所以GET不安全,POST较安全。

②GET传送的数据量较小,不能大于2kb。POST传送的数据量较大,一般默认为不受限制。

③GET服务器端用Request.QueryString来获取变量的值,POST服务器端用Request.From来获取。

④GET将数据添加到URL中来传递到服务器,通常利用一个?,后面的参数每一个数据参数以“名称=值”的形式出现,参数与参数之间利用一个连接符&来区分。POST的数据是放在HTTP主体中的,其组织方式不只一种,有&链接方式,也有分隔符方式。可以隐藏参数,传递大批数据,比较方便。

四、jsonp跨域发送请求

 首先,跨域是神马情况呢?

一个域名的组成:

http://     www  .  abc.com:   8080  / scripts/AjaxPlugin.js

协议       子域名      主域名      端口号     请求资源地址

~当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同于。

~不同域之间互相请求资源,就算作“跨域”。

所有的浏览器都遵守同源策略,这个策略能够保证一个源的动态脚本不能读取或操作其他源的http响应和cookie,这就使浏览器隔离了来自不同源的内容,防止它们互相操作。所谓同源是指协议、域名和端口都一致的情况。浏览器会阻止ajax请求非同源的内容。

JSONP(JSON with Padding) 是一种跨域请求方式。主要原理是利用了script 标签可以跨域请求的特点,由其 src 属性发送请求到服务器,服务器返回 JS 代码,网页端接受响应,然后就直接执行了,这和通过 script 标签引用外部文件的原理是一样的。但是jsonp跨域只支持get请求。

JSONP由两部分组成:回调函数和数据,回调函数一般是由网页端控制,作为参数发往服务器端,服务器端把该函数和数据拼成字符串返回。

jsonp跨域主要需要考虑三个问题:

1、因为 script 标签的 src 属性只在第一次设置的时候起作用,导致 script 标签没法重用,所以每次完成操作之后要移除;

2、JSONP这种请求方式中,参数依旧需要编码;

3、如果不设置超时,就无法得知此次请求是成功还是失败;
由于代码有点长,就放个计时器的代码吧,完整代码见AjaxPlugin

//超时处理
if(params.time){
 scriptTag.timer=setTimeout(function(){
 head.removeChild(scriptTag);
 params.fail&¶ms.fail({message:"over time"});
 window[cbName]=null;
 },params.time);
}

插件详细解析及使用方法见:https://github.com/LuckyWinty/AjaxPlugin

更多精彩内容,请点击《ajax跨域技术汇总》,进行深入学习和研究。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
使用JavaScript库还是自己写代码?
Jan 28 Javascript
jQuery操作DOM之获取表单控件的值
Jan 23 Javascript
JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
Aug 19 Javascript
Javascript实现倒计时(防页面刷新)实例
Dec 13 Javascript
JS小数转换为整数的方法分析
Jan 07 Javascript
JS 设置Cookie 有效期 检测cookie
Jun 15 Javascript
vue音乐播放器插件vue-aplayer的配置及其使用实例详解
Jul 10 Javascript
vue.js,ajax渲染页面的实例
Feb 11 Javascript
JavaScript模拟实现自由落体效果
Aug 28 Javascript
简单了解Ajax表单序列化的实现方法
Jun 14 Javascript
解决Vue调用springboot接口403跨域问题
Sep 02 Javascript
关于vue中如何监听数组变化
Apr 28 Vue.js
深入浅析Bootstrap列表组组件
May 03 #Javascript
前端jquery部分很精彩
May 03 #Javascript
jQuery代码实现对话框右上角菜单带关闭×
May 03 #Javascript
JS基于clipBoard.js插件实现剪切、复制、粘贴
May 03 #Javascript
搞定immutable.js详细说明
May 02 #Javascript
Immutable 在 JavaScript 中的应用
May 02 #Javascript
基于javascript数组实现图片轮播
May 02 #Javascript
You might like
PHP 危险函数全解析
2009/09/09 PHP
php错误提示failed to open stream: HTTP request failed!的完美解决方法
2011/06/06 PHP
自己开发Dojo的建议框架
2008/09/24 Javascript
javascript prototype 原型链
2009/03/12 Javascript
关于js中alert弹出窗口文本换行问题简单详细说明
2012/12/11 Javascript
js函数返回多个返回值的示例代码
2013/11/05 Javascript
javascript省市级联功能实现方法实例详解
2015/10/20 Javascript
javascript 显示全局变量与隐式全局变量的区别
2017/02/09 Javascript
jQuery树控件zTree使用方法详解(一)
2017/02/28 Javascript
NodeJs的fs读写删除移动监听
2017/04/28 NodeJs
浅析 NodeJs 的几种文件路径
2017/06/07 NodeJs
vue 配置多页面应用的示例代码
2018/10/22 Javascript
js表达式与运算符简单操作示例
2020/02/15 Javascript
vue 百度地图(vue-baidu-map)绘制方向箭头折线实例代码详解
2020/04/28 Javascript
[02:30]联想杯DOTA2完美世界全国高校联赛—北京站现场
2015/11/16 DOTA
[46:00]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第一局
2016/03/03 DOTA
[41:08]TNC vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python获取指定网页上所有超链接的方法
2015/04/04 Python
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
python常用库之NumPy和sklearn入门
2019/07/11 Python
Python如何输出百分比
2020/07/31 Python
如何用tempfile库创建python进程中的临时文件
2021/01/28 Python
html5的canvas实现3d雪花飘舞效果
2013/12/27 HTML / CSS
浅谈html5之sse服务器发送事件EventSource介绍
2017/08/28 HTML / CSS
viagogo英国票务平台:演唱会、体育比赛、戏剧门票
2017/03/24 全球购物
英国马匹装备和马术用品购物网站:Equine Superstore
2019/03/03 全球购物
巴塞罗那观光通票:Barcelona Pass
2019/10/30 全球购物
日语专业个人的求职信
2013/12/03 职场文书
出国留学担保书
2014/05/20 职场文书
无私奉献演讲稿
2014/09/04 职场文书
群众路线对照检查剖析材料
2014/10/09 职场文书
专题组织生活会发言材料
2014/10/17 职场文书
教师学习群众路线心得体会
2014/11/04 职场文书
给老婆的检讨书(搞笑版)
2015/05/06 职场文书
怎样写家长意见
2015/06/04 职场文书
Mysql中一千万条数据怎么快速查询
2021/12/06 MySQL