封装 ajax

128 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

封装 ajax 操作

        哪些作为参数使用

          请求方式

            type: 默认值 GET

          请求地址

        url: 必填

       是否异步

            async: 默认值 true

          是否执行 JSON.parse()

            dataType: 默认是 'string' 表示不解析, 'json'

          传递给后端的数据

            data: 'a=100&b=200' || { a: 100, b: 200 }

确定一下传递参数的方式

          function ajax() {}

          ajax('./xxx.php', null, null, 'json', 'a=100')

          ajax({ type: 'GET' })

          对象的方式传递参数

  开始封装

        1. 参数验证: 你传递的是不是符合规则

          1-1. url 验证, 必填

//公共代码部分ajax({     
url: './server/get.php',     
data: { a:100, b:200 },     
dataType: 'json',     
success: function (xhr) {  
console.log('请求成功');      
console.log('我想渲染页面, 根据结果判断登录是否成功');  
console.log(xhr);      },     
error: function (err) {      
console.log('请求失败');     
console.log(err);      }    })
function ajax(options = {}) {
if (!options.url) {       
throw new Error('url 为必填选项')     
}}

          1-2. type 验证, 可以不传递, 可以是 GET, 可以是 POST, 大小写无所谓,其他的都不行

function ajax(options = {}) {
// 1-2. 验证 type     
if (!(options.type == undefined || options.type.toUpperCase() === 'GET' || options.type.toUpperCase() === 'POST')) {
throw new Error('目前只接收 GET 或者 POST 请求方式, 请期待更新') 
}}

          1-3. async 验证, 可以不传递, 可以是 true 可以是 false

            可以不传递, 传递就是 boolean 类型

function ajax(options = {}) { 
// 1-3. 验证 async    
if (!(options.async == undefined || typeof options.async === 'boolean')) {        throw new Error('async 需要一个 Boolean 数据类型')      }}

          1-4. dataType 验证, 可以不传递, 要吗式 'string' 要吗式 'json'

function ajax(options = {}) {  
// 1-4. 验证 dataType     
if (!(options.dataType == undefined || options.dataType === 'string' || options.dataType === 'json')) {   
throw new Error('目前只支持 string 和 json 格式解析, 请期待更新')      }}

          1-5. data 验证, 可以不传递, 可以是字符串类型, 可以是 object 类型

function ajax(options = {}) { 
// 1-5. 验证 data    
if (!(options.data == undefined || typeof options.data === 'string' || Object.prototype.toString.call(options.data) === '[object Object]')) {
throw new Error('data 参数只支持 string 和 object 数据类型')      }}

          1-6. success 和  error 验证, 可以不传递, 要吗就得式函数

function ajax(options = {}) {  
// 1-6. 验证 success 和 error     
if (!(options.success == undefined || typeof options.success === 'function')) {       
throw new Error('success 传递一个函数类型')      }
 if (!(options.error == undefined || typeof options.error === 'function')) {       
 throw new Error('error 传递一个函数类型')      }}

设置一套默认值

 var _default = {       
 url: options.url,       
 // 代码能来到这里, 说名 undefined  get  post      
 type: options.type || 'GET',       
 // 代码能来到这里, 说明 undefined true false       
 // 三元表达式, 如果你式个 布尔值, 那么就用你的, 否则用 true     
 async: typeof options.async === 'boolean' ? options.async : true,     
 // 代码能来到这里, 说明 undefined 'string' 'json'      
 dataType: options.dataType || 'string',      
 // 代码能来到这里, 说明 undefined '' {}      
 data: options.data || '',       
 // 如果你传递了是一个 function, 就用你传递的, 否则我就给一个默认函数        success: options.success || function () {},  
 error: options.error || function () {}      }
      // 到这里, _default.success 和 error 肯定式一个函数
      // 2-2. 单独调整一下 data    
      // 能来到这里, _default.data 只能是 '' {}    
      if (typeof _default.data === 'object') {     
      // 准备一个空字符串       
      var str = ''       
      for (var key in _default.data) {   
      str += key + '=' + _default.data[key] + '&'        }    
      // 拼接完毕以后, 把最后一位去掉, 从新赋值给 _default.data 
      _default.data = str.slice(0, -1)      }

发送请求

var xhr = creXhr()
     // 3-1. 请求地址, 如果是 get 请求 url + '?' + data      
     // 如果式 post 请求 url      
     // 判断, 如果是 get 请求, 那么我把 _default.url 修改一下    
     if (_default.type.toUpperCase() === 'GET' && _default.data) {
     _default.url += '?' + _default.data      }      
     xhr.open(_default.type, _default.url, _default.async) 
     xhr.onreadystatechange = function () {       
     if (xhr.status >= 200 && xhr.status < 300 && xhr.readyState === 4) {          // 3-3. 判断 dataType 如果式 json 要解析   
     if (_default.dataType === 'json') {         
     // 成功, 不需要打印            
     // 调用 _default.success()          
     var res = JSON.parse(xhr.responseText)            
     // 要吗调用的式你传递进来的函数, 要吗调用的式默认函数            
     // 调用的如果式默认函数, 那么就相当于什么都没执行            
     // 如果调用的式你传递进来的函数, 那么你在函数里面写什么就执行什么 
     _default.success(res)          } 
     else if (_default.dataType === 'string') { 
     _default.success(xhr.responseText)          } 
     }
        if (xhr.readyState === 4 && xhr.status >= 400) {          
        _default.error(xhr.status)        }      }
        
      // 3-2. 判断是不是 post 请求     
      if (_default.type.toUpperCase() === 'POST') {  
      xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')      }     
      xhr.send(_default.data)    }

封装 ajax

设计模式: 为了解决特定问题而给出的简洁优化的解决方案

        懒惰模式: 多种方案选择一种的方式

          四种方式

          封装的时候要判断

          假设: 刚好是第四个可以用

          再找个页面你创建两次的时候,

            第一次要判断到第四个

            第二次还是要判断到第四个

        懒惰模式, 第一次的时候, 判断到第四个, 从第二次开始, 不再进行判断

1. 封装创建 xhr 对象

封装一个函数, 创建 xhr 对象

        不需要参数

        返回值就是一个可以再本浏览器使用的 xhr 对象

每一种创建方式写成一个函数

          依次去调用找个函数

          如果不报错, 表示这个方法可以使用

          如果 a 函数可以使用, 表示 a 函数里面的代码再当前浏览器可以正常创建

          我把 creXhr 重新赋值, 赋值为 a

          从此以后, 当你再次调用 creXhr 的时候, 其实就是再调用 a 函数

四个函数放在一个数组里面

          循环遍历这个数组

          循环的尝试

准备一个开关

          判断数组里面是不是有能执行的

          开始的时候式 false

          一旦有一个可以使用 变量赋值为 true


     function creXhr() {      
     var xhr = null// 准备一个变量       
     var flag = false
// 根据各种判断, 来给 xhr 赋值  
var arr = [        
function a() {
return new XMLHttpRequest() },       
function b() { return new ActiveXObject('Microsoft.XMLHTTP') },         function c() { return new ActiveXObject('Msxml.XMLHTTP') },      
function d() { return new ActiveXObject('Msxml2.XMLHTTP') }       ]
     
     for (let i = 0; i < arr.length; i++) {
     // arr[i] 式里面的每一个函数       
     try {        xhr = arr[i]()
     // 这里的代码可以执行, 表示 arr[i] 函数里面写的代码就是当前浏览器用的        
     creXhr = arr[i]      
     flag = true       
     break      } 
     catch (e) {}     
     }
 // 判断 flag // 如果式 false, 表示数组里面的每一个都不能用 
 if (!flag) {     
 xhr = '您的浏览器不支持 ajax, 请更换浏览器重试'      
 throw new Error(xhr)       }  
 // 返回 xhr  
 return xhr; }