基于promise封装自己的Ajax库

/**  
 * 支持的功能
 *  1.支持全局默认配置项
 *  2.发送请求_ajax.get/post..
 *  3.每一次请求都会返回promise实例,基于promise设计模式管理
 *  4.支持_ajax.all
 *  5.有实现拦截器这个功能
*/


~function(){
    //封装Ajax类
    class MyAjax{
        constructor(url,options){
          this.url = url;
          this.options = options
            return this.init();
        }
        //发送ajax请求(基于promise来管理)
        init(){
          //进行解构
          let {
            url,
            potions: {
              baseURl,
              withCredentials,
              headers,
              transformRequest,
              transformResponse,
              validateStatus,
              params,
              data,
              caches,
              methods
            }
          
          }=this;

          //保证响应拦截器中信息的合法性
          !Array.isArray(transformResponse) ? transformResponse = [] : null;
          new Array(2).fill(null).forEach((item,index)=>{
            typeof transformResponse[index] !== 'function' ? transformResponse[index] = null : null;
          })
          return new Promise((resolve,reject)=>{
             let xhr = new XMLHttpRequest;
             //URL的处理
             url = baseURl+url;
             if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(methods)){
             if(params){
               let result = ``;
               for(let attr in params){
                 if(!params.hasOwnProperty(attr)) break;
                 result = `&${attr}=${params[attr]}`;
               }
                result = result.substring(1);
                url += `${url.indexOf('?')===-1?'?':'&'}${result}`;
             }
             if(caches===false){
              url += `${url.indexOf('?')===-1?'?':'&'}_=${Math.random()}`;
             }
            }
             xhr.open(methods,url);
             xhr.onreadystatechange=()=>{
                 let resultFlag = validateStatus(xhr.status);
                 if(!resultFlag){
                   reject({
                     status:xhr.status,
                     statusText: xhr.statusText,
                     request = xhr
                  
                   });
                   return;
                 }
                 if(xhr.readyState === 4){
                   //把所有响应头变成键值对方式
                   let res_headers = {};
                   xhr.getAllResponseHeaders().split(/\n/).forEach(item=>{
                      let [key='',value=''] = item.split(':');
                      if(key.trim()==='')return;
                      res_headers[key.trim()] = value.trim();
                   });
                   resolve({
                     status: xhr.status,
                     statusText: xhr.statusText,
                    request = xhr,
                    data: JSON.parse(xhr.responseText),
                    headers : res_headers
                   });

                 }
             }
             // 跨域处理
             xhr.withCredentials = withCredentials;

             //设置请求头
             if(headers){
               for(let attr in headers){
                 if(!headers.hasOwnProperty(attr))break;
                 xhr.setRequestHeader(attr,encodeURI(headers[attr]))
               }
             }

             

             //请求拦截器:请求主体传递信息的拦截 对data的处理
             if(/^(POST|PUT)$/i.test(methods)){
             typeof transformRequest === 'function' ? data = transformRequest(data) : null;
             }else{
               data = null;
             }
             xhr.send();
          }).then(...transformResponse);  //保证在执行自己的then()之前,执行拦截器,在创建完promise实例之后直接设置拦截器的then方法
        }
    }
 
    function _init(options){

      //将_ajax.defaults和函数中的options参数进行匹配合并
      /**
       *  参数初始化:headers需要特殊处理(把用户options中传递的headers和defaults中的headers进行合并,而不是整体替换),
       * 其余的配置项直接用options中的替换defaults中的即可
       * 
       */
      let optionsHeaders = options.headers;
      _ajax.defaults.headers = Object.assign(_ajax.defaults.headers,optionsHeaders)
      delete options.headers;
      return Object.assign(_ajax.defaults,options);
    }
   function _ajax(){
    //创建全局的默认配置
    _ajax.defaults = {
        baseURl = '',
        withCredentials: false, //表示跨域请求时是否需要使用凭证
        headers:{},
        transformRequest: function (data) {
        // `transformRequest` 允许在向服务器发送前,修改请求数据
          if(!data) return data;
          let str = ``;
           //循环data
          for(let key in data){
            if(!data.hasOwnProperty(key))break;
               str = `&${key}=${data[key]}`;
           } 
          return str.substring(1);;
        },
       transformResponse: [function onFulfilled(response){
         // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
           return response.data;
        },function onRejected(reason){
          return Promise.reject(reason);
        }],
       validateStatus: function (status) {
          //http的响应状态码
         return /^(2|3)\d{2}$/.test(status);
        },
        //请求配置项
        params:{},
        data:{},
        caches: true

    }
     ["get","delete","head","options"].forEach(item=>{
       options.methods = item;
      _ajax[item] = function(url,options={}){
        return new MyAjax(url,_init(options));
      }
     });
  
   ["post","put"].forEach(item=>{
    _ajax[item] = function(url,data={},options={}){
      //把data也放到配置项目
      options.data = data;
      options.methods = item;
      return new MyAjax(url,_init(options));
    }

   })
  
   _ajax.all = function all(promiseArr = []){
       return Promise.all(promiseArr);
   }


 }

 window._ajax = _ajax; //对全局暴露_ajax;
}();


posted @ 2021-06-19 16:20  某某雅  阅读(74)  评论(0)    收藏  举报