zoukankan      html  css  js  c++  java
  • 用原生JS实现AJAX和JSONP

    前端开发在需要与后端进行数据交互时,为了方便快捷,都会选择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            
    41            // 5.连接和传输数据
    42            if(object.type == 'GET') {
    43                // 三个参数:请求方式、请求地址(get方式时,传输数据是加在地址后的)、是否异步请求(同步请求的情况极少);
    44                xhr.open(object.type, object.url + '?' + object.data, true);  
    45                xhr.send(null);  
    46             } else {  
    47                xhr.open(object.type, object.url, true);  
    48                //必须,设置提交时的内容类型  
    49                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 
    50                // 传输数据 
    51                xhr.send(object.data); 
    52             }
    53         }
    54 
    55             //data的格式化方法
    56         function formateObject(data){
    57            if(data){
    58                let arr = [];
    59                for(let name in data){
    60                    //encodeURIComponent() :用于对 URI 中的某一部分进行编码
    61                    arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
    62                }
    63 
    64                //为了防止缓存,在后面添加一个随机数
    65                arr.push('randomV=' + randomNumber());
    66                return arr.join('&');
    67            }else {
    68                console.error('无法格式化请求数据')
    69            }
    70         }
    71 
    72         //生成随机数的方法
    73         function randomNumber(){
    74             return Math.floor(Math.random()*10000+404);
    75         }
    76 
    77     };


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

    //设置Jsonp方法
            function Jsonp(object) {
              // 创建script标签并加入到页面中
              let callbackName = object.jsonp,
                  head = document.getElementsByTagName('head')[0];
              // 设置传递给后台的回调参数名  
              object.data['callback'] = callbackName;  
              let data = formateObject(object.data),
                  script = document.createElement('script');  
              head.appendChild(script);  
              // 创建JSONP的回调函数
              //创建jsonp回调函数  
              window[callbackName] = function(json) {  
                  head.removeChild(script);  
                  clearTimeout(script.timer);  
                  window[callbackName] = null;  
                  object.success && object.success(json);  
              };  
              // 发送请求
              script.src = object.url + '?' + data;  
              //为了得知此次请求是否成功,设置超时处理  
              if(object.time) {  
               script.timer = setTimeout(function() {  
                window[callbackName] = null;  
                head.removeChild(script);  
                object.error && object.error({  
                 message: '请求超时' 
                });  
               }, time);  
              }  
    
            }

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

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

    test.json内容

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

    jsonp.php内容:

    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            
     67            // 5.连接和传输数据
     68            if(object.type == 'GET') {
     69                // 三个参数:请求方式、请求地址(get方式时,传输数据是加在地址后的)、是否异步请求(同步请求的情况极少);
     70                xhr.open(object.type, object.url + '?' + object.data, true);  
     71                xhr.send(null);  
     72             } else {  
     73                xhr.open(object.type, object.url, true);  
     74                //必须,设置提交时的内容类型  
     75                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 
     76                // 传输数据 
     77                xhr.send(object.data); 
     78             }
     79         }
     80 
     81         //设置Jsonp方法
     82         function Jsonp(object) {
     83           // 创建script标签并加入到页面中
     84           let callbackName = object.jsonp,
     85               head = document.getElementsByTagName('head')[0];
     86           // 设置传递给后台的回调参数名  
     87           object.data['callback'] = callbackName;  
     88           let data = formateObject(object.data),
     89               script = document.createElement('script');  
     90           head.appendChild(script);  
     91           // 创建JSONP的回调函数
     92           //创建jsonp回调函数  
     93           window[callbackName] = function(json) {  
     94               head.removeChild(script);  
     95               clearTimeout(script.timer);  
     96               window[callbackName] = null;  
     97               object.success && object.success(json);  
     98           };  
     99           // 发送请求
    100           script.src = object.url + '?' + data;  
    101           //为了得知此次请求是否成功,设置超时处理  
    102           if(object.time) {  
    103            script.timer = setTimeout(function() {  
    104             window[callbackName] = null;  
    105             head.removeChild(script);  
    106             object.error && object.error({  
    107              message: '请求超时' 
    108             });  
    109            }, time);  
    110           }  
    111 
    112         }
    113         
    114 
    115         //data的格式化方法
    116         function formateObject(data){
    117            if(data){
    118                let arr = [];
    119                for(let name in data){
    120                    //encodeURIComponent() :用于对 URI 中的某一部分进行编码
    121                    arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
    122                }
    123 
    124                //为了防止缓存,在后面添加一个随机数
    125                arr.push('randomV=' + randomNumber());
    126                return arr.join('&');
    127            }else {
    128                console.error('无法格式化请求数据')
    129            }
    130         }
    131 
    132         //生成随机数的方法
    133         function randomNumber(){
    134             return Math.floor(Math.random()*10000+404);
    135         }
    136 
    137     };
    138 
    139 
    140     const button = document.querySelector('input[type="button"]');
    141     const btn = document.querySelector('button');
    142 
    143     const successFun = (res) => {
    144         console.log(res);
    145         let div1= document.querySelector("#div1");
    146         div1.innerHTML = res.name + res.gender;
    147     };
    148     const obj = {
    149         url : 'jsonp.php',
    150         type : 'GET',
    151         jsonp : 'callback',
    152         data : '',
    153         success: successFun,
    154         error: function(){
    155         }
    156     };
    157 
    158     const obj1 = {
    159         url : 'test.json',
    160         type : 'GET',
    161         data : '',
    162         success: successFun,
    163         error: function(){
    164         }
    165     };
    166 
    167 
    168     button.addEventListener('click', () => Ajax(obj));
    169     btn.addEventListener('click',() => Ajax(obj1));
    170 
    171     
    172  //-->
    173  </script>
    174 </html>


    测试效果:

    验证JSONP:

     

  • 相关阅读:
    两层或以上的showModalDialog解决方法
    我想学什么技术该怎样学
    中英文颜色代码参考
    来个实时更新文本框关于某个项的值
    JavaScript操作XML(一)
    关于css中的position在各大浏览器(IE,FireFox,Opera)中表现问题
    兼容IE/FF的手动触发事件的函数
    兼容各主浏览器透明的CSS
    判断浏览器类型的脚本
    Meta标签详解
  • 原文地址:https://www.cnblogs.com/liquanjiang/p/8992382.html
Copyright © 2011-2022 走看看