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

实现功能

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

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

  1. var ajax = function () {
  2.  
  3. // 做一些初始化,定义一些私有函数等
  4.  
  5. return function () {
  6. // ajax主体代码
  7. }
  8.  
  9. }()
  10.  
  11. ajax({
  12. url: myUrl,
  13. type: 'get',
  14. dataType: 'json',
    timeout: 1000,
  15. success: function (data, status) {
  16. console.log(data)
  17. },
  18. fail: function (err, status) {
  19. console.log(err)
  20. }
  21. })

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

整体思路

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

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

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

  1. var ajax = function () {
  2.  
  3. //默认请求参数
  4. var _options = {
  5. url: null,
  6. type: 'GET',
  7. data: null,
  8. dataType: 'text',
  9. jsonp: 'callback',
  10. jsonpCallback: 'jsonpCallback',
  11. async: true,
  12. cache: true,
  13. timeout:null,
  14. contentType: 'application/x-www-form-urlencoded',
  15. success: null,
  16. fail: null
  17. }
  18. // ...
  19. return function (options) {
  20. // ...
  21. }
  22. }()

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

  1. var ajax = function () {
  2.  
  3. //默认请求参数
  4. var _options = {
  5. url: null,
  6. type: 'GET',
  7. data: null,
  8. dataType: 'text',
  9. jsonp: 'callback',
  10. jsonpCallback: 'jsonpCallback',
  11. async: true,
  12. cache: true,
  13. timeout:null,
  14. contentType: 'application/x-www-form-urlencoded',
  15. success: null,
  16. fail: null
  17. }
  18. // 内部使用的继承方法
  19. var _extend = function(target,options) {
  20. if( typeof target !== 'object' || typeof options !== 'object' ) {
  21. return;
  22. }
  23. var copy ,clone, name;
  24. for( name in options ) {
  25. if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  26. target[name] = options[name];
  27. }
  28. }
  29. return target;
  30. };
  31. // ...
  32. return function (options) {
  33.  
  34. // 没有传参或者没有url,抛出错误
  35. if( !options || !options.url ) {
  36. throw('参数错误!');
  37. }
  38.  
  39. // 继承操作
  40. options.type = options.type.toUpperCase();
  41. _extend(options,_options);
  42. // ...
  43. }
  44. }()

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

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

  1. var ajax = function () {
  2.  
  3. //默认请求参数
  4. var _options = {
  5. url: null,
  6. type: 'GET',
  7. data: null,
  8. dataType: 'text',
  9. jsonp: 'callback',
  10. jsonpCallback: 'jsonpCallback',
  11. async: true,
  12. cache: true,
  13. timeout:null,
  14. contentType: 'application/x-www-form-urlencoded',
  15. success: null,
  16. fail: null
  17. }
  18. // 内部使用的继承方法
  19. var _extend = function(target,options) {
  20. if( typeof target !== 'object' || typeof options !== 'object' ) {
  21. return;
  22. }
  23. var copy ,clone, name;
  24. for( name in options ) {
  25. if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  26. target[name] = options[name];
  27. }
  28. }
  29. return target;
  30. };
  31.  
  32. // jsonp处理函数
  33. function _sendJsonpRequest(url,callbackName,succCallback) {
  34.  
  35. var script = document.createElement('script');
  36.  
  37. script.type="text/javascript";
  38. script.src=url;
  39.  
  40. document.body.appendChild(script);
  41. // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数
  42. window[callbackName] = window[callbackName] || succCallback;
  43.  
  44. }
  45.  
  46. // ...
  47. return function (options) {
  48.  
  49. // 没有传参或者没有url,抛出错误
  50. if( !options || !options.url ) {
  51. throw('参数错误!');
  52. }
  53.  
  54. // 继承操作
  55. options.type = options.type.toUpperCase();
  56. _extend(options,_options);
  57.  
  58. /*jsonp部分,直接返回*/
  59. if( options.dataType === 'jsonp' ) {
  60. var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
  61. '?' + options.jsonp+ '=' + options.jsonpCallback;
  62.  
  63. return _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
  64.  
  65. }
  66. // ...
  67. }
  68. }()

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

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

  1. var ajax = function () {
  2.  
  3. //默认请求参数
  4. var _options = {
  5. url: null,
  6. type: 'GET',
  7. data: null,
  8. dataType: 'text',
  9. jsonp: 'callback',
  10. jsonpCallback: 'jsonpCallback',
  11. async: true,
  12. cache: true,
  13. timeout:null,
  14. contentType: 'application/x-www-form-urlencoded',
  15. success: null,
  16. fail: null
  17. }
  18. // 内部使用的继承方法
  19. var _extend = function(target,options) {
  20. if( typeof target !== 'object' || typeof options !== 'object' ) {
  21. return;
  22. }
  23. var copy ,clone, name;
  24. for( name in options ) {
  25. if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  26. target[name] = options[name];
  27. }
  28. }
  29. return target;
  30. };
  31.  
  32. // jsonp处理函数
  33. function _sendJsonpRequest(url,callbackName,succCallback) {
  34.  
  35. var script = document.createElement('script');
  36.  
  37. script.type="text/javascript";
  38. script.src=url;
  39.  
  40. document.body.appendChild(script);
  41. // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数
  42. window[callbackName] = window[callbackName] || succCallback;
  43.  
  44. }
  45.  
  46. // json转化为字符串
  47. var _param = function(data) {
  48. var str = '';
  49. if( !data || _empty(data)) {
  50. return str;
  51. }
  52. for(var key in data) {
  53. str += key + '='+ data[key]+'&'
  54. }
  55. str = str.slice(0,-1);
  56. return str;
  57. }
  58. //判断对象是否为空
  59. var _empty = function(obj) {
  60. for(var key in obj) {
  61. return false;
  62. }
  63. return true;
  64. }
  65.  
  66. // ...
  67. return function (options) {
  68.  
  69. // 没有传参或者没有url,抛出错误
  70. if( !options || !options.url ) {
  71. throw('参数错误!');
  72. }
  73.  
  74. // 继承操作
  75. options.type = options.type.toUpperCase();
  76. _extend(options,_options);
  77.  
  78. /*jsonp部分,直接返回*/
  79. if( options.dataType === 'jsonp' ) {
  80. var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
  81. '?' + options.jsonp+ '=' + options.jsonpCallback;
  82.  
  83. return _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
  84.  
  85. }
  86.  
  87. //XMLHttpRequest传参无影响
  88. var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP');
  89. // get搜索字符串
  90. var search = '';
  91.  
  92. // 将data序列化
  93. var param= _param(options.data)
  94.  
  95. if( options.type === 'GET' ) {
  96. search = (options.url.indexOf('?') > -1 ? '&' : '?') + param;
  97. if(!options.cache) {
  98. search += '&radom='+Math.random();
  99. }
  100.  
  101. param = null;
  102. }
  103.  
  104. // ...
  105. }
  106. }()

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

最终的代码如下

  1. ;
  2.  
  3. var ajax = function () {
  4.  
  5. //默认请求参数
  6. var _options = {
  7. url: null,
  8. type: 'GET',
  9. data: null,
  10. dataType: 'text',
  11. jsonp: 'callback',
  12. jsonpCallback: 'jsonpCallback',
  13. async: true,
  14. cache: true,
  15. timeout:null,
  16. contentType: 'application/x-www-form-urlencoded',
  17. success: null,
  18. fail: null
  19. }
  20.  
  21. // json转化为字符串
  22. var _param = function(data) {
  23. var str = '';
  24. if( !data || _empty(data)) {
  25. return str;
  26. }
  27. for(var key in data) {
  28. str += key + '='+ data[key]+'&'
  29. }
  30. str = str.slice(0,-1);
  31. return str;
  32. }
  33. //判断对象是否为空
  34. var _empty = function(obj) {
  35. for(var key in obj) {
  36. return false;
  37. }
  38. return true;
  39. }
  40.  
  41. var _extend = function(target,options) {
  42. if( typeof target !== 'object' || typeof options !== 'object' ) {
  43. return;
  44. }
  45. var copy ,clone, name;
  46. for( name in options ) {
  47. if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) {
  48. target[name] = options[name];
  49. }
  50. }
  51. return target;
  52. };
  53.  
  54. // 自定义text转化json格式
  55. var parseJSON = function(text) {
  56. if(typeof text !== 'string') {
  57. return;
  58. }
  59. if( JSON && JSON.parse ) {
  60. return JSON.parse(text);
  61. }
  62. return (new Function('return '+text))();
  63. }
  64.  
  65. // jsonp处理函数
  66. function _sendJsonpRequest(url,callbackName,succCallback) {
  67.  
  68. var script = document.createElement('script');
  69.  
  70. script.type="text/javascript";
  71. script.src=url;
  72.  
  73. document.body.appendChild(script);
  74. // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数
  75. window[callbackName] = window[callbackName] || succCallback;
  76.  
  77. }
  78.  
  79. return function (options) {
  80.  
  81. // 没有传参或者没有url,抛出错误
  82. if( !options || !options.url ) {
  83. throw('参数错误!');
  84. }
  85.  
  86. // 继承操作
  87. options.type = options.type.toUpperCase();
  88. _extend(options,_options);
  89.  
  90. /*jsonp部分,直接返回*/
  91. if( options.dataType === 'jsonp' ) {
  92. var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url +
  93. '?' + options.jsonp+ '=' + options.jsonpCallback;
  94.  
  95. _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success);
  96.  
  97. return;
  98. }
  99.  
  100. //XMLHttpRequest传参无影响
  101. var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP');
  102.  
  103. // get搜索字符串
  104. var search = '';
  105.  
  106. // 将data序列化
  107. var param= _param(options.data)
  108.  
  109. if( options.type === 'GET' ) {
  110. search = (options.url.indexOf('?') > -1 ? '&' : '?') + param;
  111. if(!options.cache) {
  112. search += '&radom='+Math.random();
  113. }
  114.  
  115. param = null;
  116. }
  117.  
  118. xhr.open( options.type, options.url + search, options.async );
  119.  
  120. xhr.onreadystatechange = function() {
  121. if( xhr.readyState == 4 ) {
  122. if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304 ) {
  123. var text = xhr.responseText;
  124. // json格式转换
  125. if(options.dataType == 'json') {
  126. text = parseJSON(text)
  127. }
  128.  
  129. if( typeof options.success === 'function') {
  130.  
  131. options.success(text,xhr.status)
  132. }
  133.  
  134. }else {
  135.  
  136. if(typeof options.fail === 'function') {
  137. options.fail('获取失败', 500)
  138. }
  139.  
  140. }
  141. }
  142. }
  143.  
  144. xhr.setRequestHeader('content-type',options.contentType);
  145. // get请求时param时null
  146. xhr.send(param);
  147.  
  148. // 如果设置了超时,就定义
  149. if(typeof options.timeout === 'number') {
  150. // ie9+
  151. if( xhr.timeout ) {
  152. xhr.timeout = options.timeout;
  153. }else {
  154. setTimeout(function() {
  155. xhr.abort();
  156. },options.timeout)
  157. }
  158. }
  159. }
  160.  
  161. }()

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

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

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

结尾

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

能力有限,水平一般,如有错误,请指正。

jQuery之ajax实现篇的更多相关文章

  1. Jquery利用ajax调用asp.net webservice的各种数据类型(总结篇)

    原文:Jquery利用ajax调用asp.net webservice的各种数据类型(总结篇) 老话说的好:好记心不如烂笔头! 本着这原则,我把最近工作中遇到的jquery利用ajax调用web服务的 ...

  2. 【原创经验分享】JQuery(Ajax)调用WCF服务

    最近在学习这个WCF,由于刚开始学 不久,发现网上的一些WCF教程都比较简单,感觉功能跟WebService没什么特别大的区别,但是看网上的介绍,就说WCF比WebService牛逼多少多少,反正我刚 ...

  3. 深入学习jQuery选择器系列第一篇——基础选择器和层级选择器

    × 目录 [1]id选择器 [2]元素选择器 [3]类选择器[4]通配选择器[5]群组选择器[6]后代选择器[7]兄弟选择器 前面的话 选择器是jQuery的根基,在jQuery中,对事件处理.遍历D ...

  4. 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache

    虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...

  5. 对jquery的ajax进行二次封装

    第一种方法: $(function(){ /** * ajax封装 * url 发送请求的地址 * data 发送到服务器的数据,数组存储,如:{"username": " ...

  6. 网页实时聊天之js和jQuery实现ajax长轮询

    众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...

  7. 触碰jQuery:AJAX异步详解

    触碰jQuery:AJAX异步详解 传送门:异步编程系列目录…… 示例源码:触碰jQuery:AJAX异步详解.rar AJAX 全称 Asynchronous JavaScript and XML( ...

  8. jQuery调用AJAX异步详解[转]

    AJAX 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).它并非一种新的技术,而是以下几种原有技术的结合体. 1)   使用CSS和X ...

  9. jquery的ajax异步请求接收返回json数据

    http://www.jb51.net/article/51122.htm jquery的ajax异步请求接收返回json数据方法设置简单,一个是服务器处理程序是返回json数据,另一种就是ajax发 ...

随机推荐

  1. 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino

    大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...

  2. salesforce 零基础学习(六十二)获取sObject中类型为Picklist的field values(含record type)

    本篇引用以下三个链接: http://www.tgerm.com/2012/01/recordtype-specific-picklist-values.html?m=1 https://github ...

  3. nodejs进阶(2)—函数模块调用

    函数调用 1. 文件内普通函数调用 创建一个js文件命名为2_callFunction.js,其中定义一个函数fun1,向返回对象输出了一段字符串“你好,我是fun1”. //------------ ...

  4. ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式

    由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...

  5. ASP.NET SignaiR 实现消息的即时推送,并使用Push.js实现通知

    一.使用背景 1. SignalR是什么? ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指 ...

  6. 微信开发 :WeixinPayInfoCollection尚未注册Mch 问题解决

    在使用开源项目 SENPARC.WEIXIN SDK 调用微信支付接口的时候出现了WeixinPayInfoCollection尚未注册Mch,这个问题. 最后地解决方案是: 我这个傻逼忘了在全局Gl ...

  7. SHA-1算法

    SHA-1.h #ifndef _SHA1_H #define _SHA1_H #include<iostream> using namespace std; //4个函数 #define ...

  8. 【JQ基础】数组

    each() 方法规定为每个匹配元素规定运行的函数.

  9. IOS开发基础知识--碎片51

    1:https关闭证书跟域名的验证 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy]; securityPolic ...

  10. 聊聊从web session的共享到可扩展缓存设计

    先从web session的共享说起   许多系统需要提供7*24小时服务,这类系统肯定需要考虑灾备问题,单台服务器如果宕机可能无法立马恢复使用,这必定影响到服务.这个问题对于系统规模来说,从小到大可 ...