jQuery ajax的功能实现方法详解


Posted in Javascript onJanuary 06, 2017

jQuery的ajax方法非常好用,这么好的东西,你想拥有一个属于自己的ajax么?接下来,我们来自己做一个简单的ajax吧。

实现功能

由于jq中的ajax方法是用了内置的deferred模块,是Promise模式的一种实现,而我们这里没有讲过,所以我们就不使用这一模式啦。

我们只定义一个ajax方法,他可以简单的get,post,jsonp请求就可以啦~~

var ajax = function () {
 // 做一些初始化,定义一些私有函数等
 return function () {
 // ajax主体代码
 }
}()
ajax({
 url: myUrl,
 type: 'get',
 dataType: 'json',
 timeout: 1000,
 success: function (data, status) {
 console.log(data)
 },
 fail: function (err, status) {
 console.log(err)
 }
})

我们的ajax方法最后实现的功能如上所示,非常类似于jq。那我们还在等什么,开始吧。

整体思路

我们的ajax方法需要传递一个对象进去,这个对象中我们可以定义一些我们希望的属性,我们就必须初始一下各种属性

//默认请求参数
 var _options = {
 url: null, // 请求连接
 type: 'GET', // 请求类型
 data: null, // post时请求体
 dataType: 'text', // 返回请求的类型,有text/json两种
 jsonp: 'callback', // jsonp请求的标志,一般不改动
 jsonpCallback: 'jsonpCallback', //jsonp请求的函数名
 async: true, // 是否异步
 cache: true, // 是否缓存
 timeout:null, // 设置请求超时
 contentType: 'application/x-www-form-urlencoded',
 success: null, // 请求成功回调函数
 fail: null // 请求失败回调
 }

以上我们定义了一大串请求有关的数据,接下来我们就开始ajax主体函数的书写,现在的ajax方法是这样了

var ajax = function () {
 //默认请求参数
 var _options = {
 url: null,
 type: 'GET',
 data: null,
 dataType: 'text',
 jsonp: 'callback',
 jsonpCallback: 'jsonpCallback',
 async: true,
 cache: true,
 timeout:null,
 contentType: 'application/x-www-form-urlencoded',
 success: null,
 fail: null
 }
 // ...
 return function (options) {
  // ...
 }
}()

我们可以想一下,ajax方法传递一个对象进来,我们是不是需要把我们设置的这个对象上的属性来覆盖掉初始化_options上面的那些属性呢,肯定需要。那下面我们先写一个简单的继承,如下:

var ajax = function () {
 //默认请求参数
 var _options = {
 url: null,
 type: 'GET',
 data: null,
 dataType: 'text',
 jsonp: 'callback',
 jsonpCallback: 'jsonpCallback',
 async: true,
 cache: true,
 timeout:null,
 contentType: 'application/x-www-form-urlencoded',
 success: null,
 fail: null
 }
 // 内部使用的继承方法
 var _extend = function(target,options) {
 if( typeof target !== 'object' || typeof options !== 'object' ) {
  return;
 }
 var copy ,clone, name;
 for( name in options ) {
  if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  target[name] = options[name];
  }
 }
 return target;
 };
 // ...
 return function (options) {
 // 没有传参或者没有url,抛出错误
 if( !options || !options.url ) {
  throw('参数错误!');
 }
 // 继承操作
 options.type = options.type.toUpperCase();
 _extend(options,_options);
  // ...
 }
}()

这个继承方法,我们是把初始化的_options继承到了options,为什么呢?因为我们这个_options对象不在ajax方法内部,我们需要使用它,但我们不能改变他,如果改变了他,下一次使用ajax方法将会崩溃。因此,我们紧紧是把配置的options对象没有的属性设置为初始值。

下面,我们就要发送请求了么?等等!好像jsonp请求不是xhr请求啊,他好像是将请求url当做script标签的src值插入到页面body中去实现的,哦,对了,我们先把jsonp请求处理一下再开始建立xhr请求的代码吧。

var ajax = function () {
 //默认请求参数
 var _options = {
 url: null,
 type: 'GET',
 data: null,
 dataType: 'text',
 jsonp: 'callback',
 jsonpCallback: 'jsonpCallback',
 async: true,
 cache: true,
 timeout:null,
 contentType: 'application/x-www-form-urlencoded',
 success: null,
 fail: null
 }
 // 内部使用的继承方法
 var _extend = function(target,options) {
 if( typeof target !== 'object' || typeof options !== 'object' ) {
  return;
 }
 var copy ,clone, name;
 for( name in options ) {
  if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  target[name] = options[name];
  }
 }
 return target;
 };
 // jsonp处理函数
 function _sendJsonpRequest(url,callbackName,succCallback) {
 var script = document.createElement('script');
 script.type="text/javascript";
 script.src=url;
 document.body.appendChild(script);
 // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数
 window[callbackName] = window[callbackName] || succCallback;
 }
 // ...
 return function (options) {
 // 没有传参或者没有url,抛出错误
 if( !options || !options.url ) {
  throw('参数错误!');
 }
 // 继承操作
 options.type = options.type.toUpperCase();
 _extend(options,_options);
 /*jsonp部分,直接返回*/
 if( options.dataType === 'jsonp' ) {
  var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
  '?' + options.jsonp+ '=' + options.jsonpCallback;
  return _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
 }
  // ...
 }
}()

我们定义了一个_sendJsonpRequest函数,这个函数接收三个参数,第一个是jsonpUrl,第二个是jsonp的回调函数名,第三个是成功回调函数,我们在这个函数内建立一个src为jsonpUrl的script元素插入到body中,同时,确定了回调函数(如果我们定义了jsonpCallback函数就调用它,如果没有就调用success回调,一般情况我们不去定义全局的jsonpCallback函数而传递success回调来完成jsonp请求)。

好,处理好jsonp请求后,我们开始处理xhr请求了。

var ajax = function () {
 //默认请求参数
 var _options = {
 url: null,
 type: 'GET',
 data: null,
 dataType: 'text',
 jsonp: 'callback',
 jsonpCallback: 'jsonpCallback',
 async: true,
 cache: true,
 timeout:null,
 contentType: 'application/x-www-form-urlencoded',
 success: null,
 fail: null
 }
 // 内部使用的继承方法
 var _extend = function(target,options) {
 if( typeof target !== 'object' || typeof options !== 'object' ) {
  return;
 }
 var copy ,clone, name;
 for( name in options ) {
  if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  target[name] = options[name];
  }
 }
 return target;
 };
 // jsonp处理函数
 function _sendJsonpRequest(url,callbackName,succCallback) {
 var script = document.createElement('script');
 script.type="text/javascript";
 script.src=url;
 document.body.appendChild(script);
 // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数
 window[callbackName] = window[callbackName] || succCallback;
 }
 // json转化为字符串
 var _param = function(data) {
 var str = '';
 if( !data || _empty(data)) {
  return str;
 }
 for(var key in data) {
  str += key + '='+ data[key]+'&'
 }
 str = str.slice(0,-1);
 return str;
 }
 //判断对象是否为空
 var _empty = function(obj) {
 for(var key in obj) {
  return false;
 }
 return true;
 }
 // ...
 return function (options) {
 // 没有传参或者没有url,抛出错误
 if( !options || !options.url ) {
  throw('参数错误!');
 }
 // 继承操作
 options.type = options.type.toUpperCase();
 _extend(options,_options);
 /*jsonp部分,直接返回*/
 if( options.dataType === 'jsonp' ) {
  var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
  '?' + options.jsonp+ '=' + options.jsonpCallback;
  return _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
 }
  //XMLHttpRequest传参无影响
 var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP');
 // get搜索字符串
 var search = '';
 // 将data序列化
 var param= _param(options.data)
 if( options.type === 'GET' ) {
  search = (options.url.indexOf('?') > -1 ? '&' : '?') + param;
  if(!options.cache) {
  search += '&radom='+Math.random();
  }
  param = null;
 }
  // ...
 }
}()

首先,兼容ie创建xhr对象,XMLHttpRequest构造函数传递参数是无影响,然后我们定义了两个辅助变量:search、param,前者用于get请求的查询字串,后者用于post请求的send内容,我们定义了一个_param方法来讲对象转换为send方法参数的模式,就如你看到的那样,下面我们做了get与post之间合理的search、param的赋值工作。接下来我们就可以发送请求书写最激动人心的内容了。

最终的代码如下

;
var ajax = function () {
 //默认请求参数
 var _options = {
 url: null,
 type: 'GET',
 data: null,
 dataType: 'text',
 jsonp: 'callback',
 jsonpCallback: 'jsonpCallback',
 async: true,
 cache: true,
 timeout:null,
 contentType: 'application/x-www-form-urlencoded',
 success: null,
 fail: null
 }
 // json转化为字符串
 var _param = function(data) {
 var str = '';
 if( !data || _empty(data)) {
  return str;
 }
 for(var key in data) {
  str += key + '='+ data[key]+'&'
 }
 str = str.slice(0,-1);
 return str;
 }
 //判断对象是否为空
 var _empty = function(obj) {
 for(var key in obj) {
  return false;
 }
 return true;
 }
 var _extend = function(target,options) {
 if( typeof target !== 'object' || typeof options !== 'object' ) {
  return;
 }
 var copy ,clone, name;
 for( name in options ) {
  if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  target[name] = options[name];
  }
 }
 return target;
 };
 // 自定义text转化json格式
 var parseJSON = function(text) {
 if(typeof text !== 'string') {
  return;
 }
 if( JSON && JSON.parse ) {
  return JSON.parse(text);
 }
 return (new Function('return '+text))();
 }
 // jsonp处理函数
 function _sendJsonpRequest(url,callbackName,succCallback) {
 var script = document.createElement('script');
 script.type="text/javascript";
 script.src=url;
 document.body.appendChild(script);
 // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数
 window[callbackName] = window[callbackName] || succCallback;
 }
 return function (options) {
 // 没有传参或者没有url,抛出错误
 if( !options || !options.url ) {
  throw('参数错误!');
 }
 // 继承操作
 options.type = options.type.toUpperCase();
 _extend(options,_options);
 /*jsonp部分,直接返回*/
 if( options.dataType === 'jsonp' ) {
  var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
  '?' + options.jsonp+ '=' + options.jsonpCallback;
  _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
  return;
 }
  //XMLHttpRequest传参无影响
 var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP');
 // get搜索字符串
 var search = '';
 // 将data序列化
 var param= _param(options.data)
 if( options.type === 'GET' ) {
  search = (options.url.indexOf('?') > -1 ? '&' : '?') + param;
  if(!options.cache) {
  search += '&radom='+Math.random();
  }
  param = null;
 }
 xhr.open( options.type, options.url + search, options.async );
 xhr.onreadystatechange = function() {
  if( xhr.readyState == 4 ) {
  if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304 ) {
   var text = xhr.responseText;
   // json格式转换
   if(options.dataType == 'json') {
    text = parseJSON(text)
   }
   if( typeof options.success === 'function') {
   options.success(text,xhr.status)
   }
  }else {
   if(typeof options.fail === 'function') {
   options.fail('获取失败', 500)
   }
  }
  }
 }
 xhr.setRequestHeader('content-type',options.contentType);
 // get请求时param时null
 xhr.send(param);
 // 如果设置了超时,就定义
 if(typeof options.timeout === 'number') {
  // ie9+
  if( xhr.timeout ) {
  xhr.timeout = options.timeout;
  }else {
  setTimeout(function() {
   xhr.abort();
  },options.timeout)
  }
 }
 }
}()

可以看到,我们很熟悉的xhr代码,在这里,我们需要写一个解析返回字串形成json格式对象的方法parseJSON,类似于jq中的parseJSON方法,如上所示。

我们还需要设置超时代码,如果设置了请求超时,我们就如上定义。

注意:上面代码中,由于懒,设置请求头一行并没有判断是否在post请求下,你可以自己设置~~~。

结尾

一个简单的ajax方法就完成了,你是否也完成了呢?如果你懂deferred,你可以尝试着书写为deferred格式,很简单的~~~。

以上所述是小编给大家介绍的jQuery ajax的功能实现方法详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript+iframe 实现无刷新载入整页的代码
Mar 17 Javascript
JavaScript的类型简单说明
Sep 03 Javascript
利用try-catch判断变量是已声明未声明还是未赋值
Mar 12 Javascript
Javascript 函数parseInt()转换时出现bug问题
May 20 Javascript
详解javascript中的事件处理
Nov 06 Javascript
全面解析Bootstrap图片轮播效果
Dec 03 Javascript
基于jquery实现省市区三级联动效果
Dec 25 Javascript
详解Bootstrap按钮
Jan 04 Javascript
AngularJS 所有版本下载地址
Sep 14 Javascript
JavaScript组件开发之输入框加候选框
Mar 10 Javascript
详解微信小程序与内嵌网页交互实现支付功能
Oct 22 Javascript
Element 默认勾选表格 toggleRowSelection的实现
Sep 04 Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
Jan 06 #Javascript
Jqprint实现页面打印
Jan 06 #Javascript
JS使用正则截取两个字符串之间的字符串实现方法详解
Jan 06 #Javascript
jQuery EasyUi 验证功能实例解析
Jan 06 #Javascript
jQuery编写网页版2048小游戏
Jan 06 #Javascript
利用JQuery实现datatables插件的增加和删除行功能
Jan 06 #Javascript
javascript正则表达式模糊匹配IP地址功能示例
Jan 06 #Javascript
You might like
PHP memcache扩展的三种安装方法
2009/04/26 PHP
浅析application/x-www-form-urlencoded和multipart/form-data的区别
2014/06/22 PHP
基于PHP实现用户注册登录功能
2016/10/14 PHP
php-fpm.conf配置文件中文说明详解及重要参数说明
2018/10/10 PHP
JavaScript的模块化:封装(闭包),继承(原型) 介绍
2013/07/22 Javascript
js 与 php 通过json数据进行通讯示例
2014/03/26 Javascript
javascript实现获取浏览器版本、操作系统类型
2015/01/29 Javascript
javascript中$(function() {});写与不写有哪些区别
2015/08/10 Javascript
JS+CSS实现精美的二级导航效果代码
2015/09/17 Javascript
jquery ajax结合thinkphp的getjson实现跨域的方法
2016/06/06 Javascript
纯js和css完成贪吃蛇小游戏demo
2016/09/01 Javascript
自定义require函数让浏览器按需加载Js文件
2016/11/24 Javascript
vue-cli+webpack在生成的项目中使用bootstrap实例代码
2017/05/26 Javascript
AngularJS 最常用的八种功能(基础知识)
2017/06/26 Javascript
详解Nodejs 通过 fs.createWriteStream 保存文件
2017/10/10 NodeJs
浅谈es6中export和export default的作用及区别
2018/02/07 Javascript
TypeScript基础入门教程之三重斜线指令详解
2018/10/22 Javascript
vue实现移动端悬浮窗效果
2018/12/01 Javascript
JS散列表碰撞处理、开链法、HashTable散列示例
2019/02/08 Javascript
Vue 幸运大转盘实现思路详解
2019/05/06 Javascript
[01:32:22]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第一场 2月5日
2021/03/11 DOTA
Python for循环与range函数的使用详解
2019/03/23 Python
浅析python内置模块collections
2019/11/15 Python
Keras实现DenseNet结构操作
2020/07/06 Python
简述python Scrapy框架
2020/08/17 Python
python音频处理的示例详解
2020/12/23 Python
HTML5 script元素async、defer异步加载使用介绍
2013/08/23 HTML / CSS
瑞士网球商店:Tennis-Point
2020/03/12 全球购物
为数据库创建索引都需要注意些什么
2012/07/17 面试题
网络方面基础面试题
2012/11/16 面试题
青年创业培训欢迎词
2014/01/10 职场文书
大学生村官演讲稿
2014/04/25 职场文书
庆六一活动总结
2014/08/29 职场文书
2014学习优秀共产党员先进事迹思想汇报
2014/09/14 职场文书
本科毕业论文导师评语
2014/12/31 职场文书
未婚证明格式
2015/06/15 职场文书