前端开发在需要与后端进行数据交互时,为了方便快捷,都会选择JQuery中封装的AJAX方法,但是有些时候,我们只需要JQuery的AJAX请求方法,而其他的功能用到的很少,这显然是没必要的。其实,原生JavaScript实现AJAX并不难,下面我们可是演示如何实现利用原生JS构建简单的AJAX,还有跨域请求JSONP的实现。

AJAX的根本是XMLHttprequest,而一个完整的AJAX请求一般包括以下步骤:

  • 实例化XMLHttpRequest对象
  • 连接服务器
  • 发送请求
  • 接收响应数据

下面我们使用原生JS封装一个简单地ajax()方法:

  1.  const Ajax = (object) => {
  2. object = object || {};
  3. object.data = object.data || {};
  4. //判断请求类型为AJAX或者JSONP
  5. let json = object.jsonp ? Jsonp(object) : ajax(object);
  6.  
  7. //设置ajax方法
  8. function ajax(object) {
  9. // 1.设置请求方式:如果没有制定则默认为GET
  10. object.type = (object.type || 'GET').toUpperCase();
  11. // 2.设置data数据的格式化
  12. object.data = formateObject(object.data);
  13. // 3.实例化XMLHttpRequest对象
  14. var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  15. // 4.监听事件,只要readyState改变,就会调用readystatechange事件
  16. xhr.onreadystatechange = function(){
  17. // readyState属性表示请求/响应过程的当前活动阶段,4为完成,已经接收到全部响应数据
  18. if(xhr.readyState == 4) {
  19. let status = xhr.status;
  20. // status : HTTP响应的状态码,2开头表示成功
  21. if(status >=200 && status < 300){
  22. let response = '';
  23. // 判断接受数据的内容类型
  24. let type = xhr.getResponseHeader('Content-type');
  25. if(type.indexOf('xml') !== -1 && xhr.responseXML) {
  26. response = xhr.responseXML; //Document对象响应
  27. } else if(type === 'application/json') {
  28. response = JSON.parse(xhr.responseText); //JSON响应
  29. } else {
  30. response = xhr.responseText; //字符串响应
  31. };
  32. // 成功回调函数
  33. object.success && object.success(response);
  34. }else {
  35. object.error && object.error(response);
  36. }
  37. }
  38. }
  39.  
  40. // 5.连接和传输数据
  41. if(object.type == 'GET') {
  42. // 三个参数:请求方式、请求地址(get方式时,传输数据是加在地址后的)、是否异步请求(同步请求的情况极少);
  43. xhr.open(object.type, object.url + '?' + object.data, true);
  44. xhr.send(null);
  45. } else {
  46. xhr.open(object.type, object.url, true);
  47. //必须,设置提交时的内容类型
  48. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
  49. // 传输数据
  50. xhr.send(object.data);
  51. }
  52. }
  53.  
  54. //data的格式化方法
  55. function formateObject(data){
  56. if(data){
  57. let arr = [];
  58. for(let name in data){
  59. //encodeURIComponent() :用于对 URI 中的某一部分进行编码
  60. arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
  61. }
  62.  
  63. //为了防止缓存,在后面添加一个随机数
  64. arr.push('randomV=' + randomNumber());
  65. return arr.join('&');
  66. }else {
  67. console.error('无法格式化请求数据')
  68. }
  69. }
  70.  
  71. //生成随机数的方法
  72. function randomNumber(){
  73. return Math.floor(Math.random()*10000+404);
  74. }
  75.  
  76. };

同理,我们也可以实现一个JSONP的方法

  1. //设置Jsonp方法
  2. function Jsonp(object) {
  3. // 创建script标签并加入到页面中
  4. let callbackName = object.jsonp,
  5. head = document.getElementsByTagName('head')[0];
  6. // 设置传递给后台的回调参数名
  7. object.data['callback'] = callbackName;
  8. let data = formateObject(object.data),
  9. script = document.createElement('script');
  10. head.appendChild(script);
  11. // 创建JSONP的回调函数
  12. //创建jsonp回调函数
  13. window[callbackName] = function(json) {
  14. head.removeChild(script);
  15. clearTimeout(script.timer);
  16. window[callbackName] = null;
  17. object.success && object.success(json);
  18. };
  19. // 发送请求
  20. script.src = object.url + '?' + data;
  21. //为了得知此次请求是否成功,设置超时处理
  22. if(object.time) {
  23. script.timer = setTimeout(function() {
  24. window[callbackName] = null;
  25. head.removeChild(script);
  26. object.error && object.error({
  27. message: '请求超时'
  28. });
  29. }, time);
  30. }
  31.  
  32. }

下面我们来尝试一下这两个方法是否管用
新建一个index.html文件,新建一个test.json和jsonp.php

利用nginx搭建一个简单地服务器,因为谷歌默认不允许本地文件进行ajax请求:

test.json内容

  1. {
  2. "name" : "111",
  3. "gender" : "222"
  4. }

jsonp.php内容:

  1. callback({"name":"李大师","gender":"是前端开发工程师"})

index.html内容

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="Generator" content="EditPlus®">
  6. <meta name="Author" content="">
  7. <meta name="Keywords" content="">
  8. <meta name="Description" content="">
  9. <title>原生JS实现ajax和JSONP请求</title>
  10. <style type="text/css">
  11. input[type='button'] {
  12. margin:20px;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <button>点击验证AJAX</button>
  18. <input type="button" value="点击验证JSONP" onclick="">
  19. <div id="div1" class="">
  20.  
  21. </div>
  22. </body>
  23. <script type="text/javascript">
  24. <!--
  25. //原生JS方法封装AJAX请求和JSONP请求
  26.  
  27. window.Ajax = (object) => {
  28. object = object || {};
  29. object.data = object.data || {};
  30. //判断请求类型为AJAX或者JSONP
  31. let json = object.jsonp ? Jsonp(object) : ajax(object);
  32.  
  33. //设置ajax方法
  34. function ajax(object) {
  35. // 1.设置请求方式:如果没有制定则默认为GET
  36. object.type = (object.type || 'GET').toUpperCase();
  37. // 2.设置data数据的格式化
  38. object.data = formateObject(object.data);
  39. // 3.实例化XMLHttpRequest对象
  40. var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  41. // 4.监听事件,只要readyState改变,就会调用readystatechange事件
  42. xhr.onreadystatechange = function(){
  43. // readyState属性表示请求/响应过程的当前活动阶段,4为完成,已经接收到全部响应数据
  44. if(xhr.readyState == 4) {
  45. let status = xhr.status;
  46. // status : HTTP响应的状态码,2开头表示成功
  47. if(status >=200 && status < 300){
  48. let response = '';
  49. // 判断接受数据的内容类型
  50. let type = xhr.getResponseHeader('Content-type');
  51. if(type.indexOf('xml') !== -1 && xhr.responseXML) {
  52. response = xhr.responseXML; //Document对象响应
  53. } else if(type === 'application/json') {
  54. response = JSON.parse(xhr.responseText); //JSON响应
  55. } else {
  56. response = xhr.responseText; //字符串响应
  57. };
  58. // 成功回调函数
  59. object.success && object.success(response);
  60. }else {
  61. object.error && object.error(response);
  62. }
  63. }
  64. }
  65.  
  66. // 5.连接和传输数据
  67. if(object.type == 'GET') {
  68. // 三个参数:请求方式、请求地址(get方式时,传输数据是加在地址后的)、是否异步请求(同步请求的情况极少);
  69. xhr.open(object.type, object.url + '?' + object.data, true);
  70. xhr.send(null);
  71. } else {
  72. xhr.open(object.type, object.url, true);
  73. //必须,设置提交时的内容类型
  74. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
  75. // 传输数据
  76. xhr.send(object.data);
  77. }
  78. }
  79.  
  80. //设置Jsonp方法
  81. function Jsonp(object) {
  82. // 创建script标签并加入到页面中
  83. let callbackName = object.jsonp,
  84. head = document.getElementsByTagName('head')[0];
  85. // 设置传递给后台的回调参数名
  86. object.data['callback'] = callbackName;
  87. let data = formateObject(object.data),
  88. script = document.createElement('script');
  89. head.appendChild(script);
  90. // 创建JSONP的回调函数
  91. //创建jsonp回调函数
  92. window[callbackName] = function(json) {
  93. head.removeChild(script);
  94. clearTimeout(script.timer);
  95. window[callbackName] = null;
  96. object.success && object.success(json);
  97. };
  98. // 发送请求
  99. script.src = object.url + '?' + data;
  100. //为了得知此次请求是否成功,设置超时处理
  101. if(object.time) {
  102. script.timer = setTimeout(function() {
  103. window[callbackName] = null;
  104. head.removeChild(script);
  105. object.error && object.error({
  106. message: '请求超时'
  107. });
  108. }, time);
  109. }
  110.  
  111. }
  112.  
  113. //data的格式化方法
  114. function formateObject(data){
  115. if(data){
  116. let arr = [];
  117. for(let name in data){
  118. //encodeURIComponent() :用于对 URI 中的某一部分进行编码
  119. arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
  120. }
  121.  
  122. //为了防止缓存,在后面添加一个随机数
  123. arr.push('randomV=' + randomNumber());
  124. return arr.join('&');
  125. }else {
  126. console.error('无法格式化请求数据')
  127. }
  128. }
  129.  
  130. //生成随机数的方法
  131. function randomNumber(){
  132. return Math.floor(Math.random()*10000+404);
  133. }
  134.  
  135. };
  136.  
  137. const button = document.querySelector('input[type="button"]');
  138. const btn = document.querySelector('button');
  139.  
  140. const successFun = (res) => {
  141. console.log(res);
  142. let div1= document.querySelector("#div1");
  143. div1.innerHTML = res.name + res.gender;
  144. };
  145. const obj = {
  146. url : 'jsonp.php',
  147. type : 'GET',
  148. jsonp : 'callback',
  149. data : '',
  150. success: successFun,
  151. error: function(){
  152. }
  153. };
  154.  
  155. const obj1 = {
  156. url : 'test.json',
  157. type : 'GET',
  158. data : '',
  159. success: successFun,
  160. error: function(){
  161. }
  162. };
  163.  
  164. button.addEventListener('click', () => Ajax(obj));
  165. btn.addEventListener('click',() => Ajax(obj1));
  166.  
  167. //-->
  168. </script>
  169. </html>

测试效果:

验证JSONP:

用原生JS实现AJAX和JSONP的更多相关文章

  1. 用原生js实现ajax、jsonp

    转载: http://www.cnblogs.com/yangheng/p/6065910.html 一.原生js实现ajax $.ajax({ url: '', type: 'post', data ...

  2. 原生JS实现AJAX、JSONP及DOM加载完成事件,并提供对应方法

    JS原生AJAX ajax:一种请求数据的方式,不需要刷新整个页面: ajax的技术核心是 XMLHttpRequest 对象: ajax 请求过程:创建 XMLHttpRequest 对象.连接服务 ...

  3. 原生JS实现AJAX、JSONP及DOM加载完成事件

    一.JS原生Ajax ajax:一种请求数据的方式,不需要刷新整个页面:ajax的技术核心是 XMLHttpRequest 对象:ajax 请求过程:创建 XMLHttpRequest 对象.连接服务 ...

  4. 原生JS实现Ajax及Ajax的跨域请求

      前  言          如今,从事前端方面的程序猿们,如果,不懂一些前后台的数据交互方面的知识的话,估计都不太好意思说自己是程序猿.当然,如今有着许多的框架,都有相对应的前后台数据交互的方法. ...

  5. 原生js实现Ajax

    一般来说,大家可能都会习惯用JQuery提供的Ajax方法,但是用原生的js怎么去实现Ajax方法呢? JQuery提供的Ajax方法: $.ajax({ url: , type: '', dataT ...

  6. 使用原生js写ajax

    // 使用原生js 封装ajax // 兼容xhr对象 function createXHR(){ if(typeof XMLHttpRequest != "undefined") ...

  7. 表单验证--通过原生js模仿ajax的异步交互

    今天给大家带来个福利,我也是刚刚学习的很实用的一个东西,通过原生js模仿ajax的异步交互. 我的博客只是给那些新手看的大神勿喷,写的不好可留言,请指出. 因为当初自己学的时候一个问题不会找人问,知道 ...

  8. 原生JS的Ajax技术

    1.同步和异步 同步现象:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待  卡死状态 异步现象:客户端发送请求到服务器端,无论服务器是否返回响应,客户端都可以随意做其他事情,不会被卡 ...

  9. 原生js中用Ajax进行get传参

    原生js中用Ajax进行get传参 案例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...

随机推荐

  1. 磁盘大保健 保持你的Linux服务器存储健康

    df du -sh *| sort -nr du -h --max-depth=1 / du -h --max-depth=1 /* find . -type f -size +1000000k 查找 ...

  2. 【基础算法-模拟-例题-金币】-C++

    原题链接:P2669 金币 这道题目完全是一道模拟题,只要按照题目中的加金币的算法和sum累加就可以很轻易得出最终答案. 说一下有一些点需要注意: 1.用i来计每天发的金币数,n来计已经拿了金币的天数 ...

  3. I/O的简介

    文本我们能读懂的都可以认为是字符流,文章 java文件都是字符流数据 流的分类 输入流 输出流 1.输出流 Writer:关于字符流的父类,抽象类.与之相对的输入流 Reader类 一.字符流 字符流 ...

  4. md文件的书写《一》

    标题 :标题大小取决于#的多少 嵌套标题 使用 * - + 中的任一个加空格就可以实现创建列表 多层嵌套 我见青山多妩媚 (右边的尖括号加内容,实现引用) 这是第一段文字. 这是第二段文字. 段落以回 ...

  5. Java秒杀系统实战系列~构建SpringBoot多模块项目

    摘要:本篇博文是“Java秒杀系统实战系列文章”的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项目,即“秒杀系统”! ...

  6. linux初学者-iptables篇

     linux初学者-iptables篇 iptables是防火墙的一种,是用来设置.维护和检查linux内核的IP过滤规则的,可以完成封包过滤.封包重定向和网络地址转换(NAT)等功能. iptabl ...

  7. 动手造轮子:基于 Redis 实现 EventBus

    动手造轮子:基于 Redis 实现 EventBus Intro 上次我们造了一个简单的基于内存的 EventBus,但是如果要跨系统的话就不合适了,所以有了这篇基于 Redis 的 EventBus ...

  8. HelloDjango 系列教程:创建 Django 博客的数据库模型

    文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 设计博客的数据库表结构 博客最主要的功能就是展示我们写的文章,它需要从某个地方获取博客文章数据才能把文章展示出来,通常来说这个 ...

  9. 基于Spark Grahpx+Neo4j 实现用户社群发现

    上一篇文章知识图谱在大数据中的应用我们介绍了知识图谱的一些概念和应用场景,今天我们就来看一个具体的应用案例了解下知识图谱的应用.用户增长对于一个APP的生存起到了至关重要的作用,没有持续的用户增长,再 ...

  10. 【pip】brew install pip 问题

    Mac 下用 brew install pip 命令安装 pip 时报错: Error: No available formula with the name "pip" Home ...