前端请求优雅降级之Service封装

368 阅读2分钟

Service.js: aladdin > ajax > xhr

function Service() {  this.request = function(opts) {    this.opts = {...Service.DEFAULTS, ...opts}    if (window.aladdin && window.aladdin.http && window.aladdin.http.request) {      return this._aladdinRequest()    } else if (window.$ && window.$.ajax) {      return this._ajaxRequest()    } else { // 原生请求      return this._xhrRequest()    }  }  this.get = function (opts) {    return this.request((opts.method = "GET") && opts)  }  this.post = function (opts) {    return this.request((opts.method = "POST") && opts)  }}Service.DEFAULTS = {  url: '',  method: 'GET',  headers: { // HTTP信息头对象    contentType: 'application/x-www-form-urlencoded;charset=utf-8'  },  timeout: 15000, // 请求超时设置,毫秒  data: {}}/** * aladdin发送请求 */Service.prototype._aladdinRequest = function () {  const config = {    url: this.opts.url,    method: this.opts.method,    headers: this.opts.headers,    timeout: this.opts.timeout,    xhrFields: {      withCredentials: true    }  }  if (config.method.toUpperCase() === 'POST') {    config.body = this.opts.data  } else {    config.qs = this.opts.data  }  return new Promise(function(resolve, reject) {    window.aladdin.http.request(config, function (error, res) {      // 请求失败      if (error) {         reject({          status: error.code, //错误代码          statusText: error.message //具体错误信息        })        return      }      // 请求成功      if (res.status === 200) {        isJsonStr(res.body) ? resolve(JSON.parse(res.body)) : resolve(res.body) //res.body 响应原始内容      } else {        reject({          status: res.status, //响应状态码,如 401          statusText: res.statusText //响应状态码对应的文本,如 'Unauthorized'        })      }    })  })}/** * ajax发送请求 */Service.prototype._ajaxRequest = function () {  let config = {    url: this.opts.url,    type: this.opts.method,    data: this.opts.data, // 如果是GET请求,它会自动被作为参数拼接到url上    headers: this.opts.headers,    // dataType: 'json', // 默认none。假若设置json,请求成功200但返回类型为text,会造成解析错误走error回调    timeout: this.opts.timeout,    xhrFields: {      withCredentials: true    }  }  return new Promise(function(resolve, reject) {    // 请求成功    config.success = function(data, status, xhr) {      if (xhr.status === 200) {        isJsonStr(data) ? resolve(JSON.parse(data)) : resolve(data) //data 响应原始内容      } else {        reject({          status: xhr.status, // 响应状态码          statusText: xhr.statusText // 状态码对应的文本        })      }    }    // 请求失败 (超时,解析错误,或者状态码不在HTTP 2xx)    config.error = function(xhr) {      reject({        status: xhr.status, // 响应状态码        statusText: xhr.statusText // 状态码对应的文本      })    }    window.$.ajax(config)  })}/** * XMLHttpRequest发送请求 */Service.prototype._xhrRequest = function () {  let url = this.opts.url  const method = this.opts.method.toUpperCase()  const data = this.opts.data  // 若是 GET 请求,需要处理 data 里的数据并且以一定的规则拼接到 url 后  if (method === 'GET') {    var formData = []    for(let key in this.opts.data) {      formData.push(''.concat(key, '=', this.opts.data[key]))    }    let params = formData.join('&')    if (params.length > 0) {      url += url.indexOf('?') >= 0 ? ''.concat('&', params) : ''.concat('?', params)    }  }  let xhr = null  if (window.XMLHttpRequest) {    xhr = new XMLHttpRequest()  } else if (window.ActiveXObject) {    xhr=new window.ActiveXObject("Microsoft.XMLHTTP")  }  xhr.timeout = this.opts.timeout  xhr.withCredentials = true  xhr.open(method, url, true)  for(let key in this.opts.headers) {    xhr.setRequestHeader(key, this.opts.headers[key])  }  return new Promise(function(resolve, reject) {    xhr.onreadystatechange = function() {      if (xhr.readyState === 4) {        // 请求成功        if (xhr.status === 200) {          isJsonStr(xhr.response) ? resolve(JSON.parse(xhr.response)) : resolve(xhr.response) // xhr.response,整个响应体        } else {          reject({            status: xhr.status, // 响应状态码            statusText: xhr.statusText // 状态码对应的文本          })        }      }    }    xhr.onerror = xhr.ontimeout = function() {      reject({        status: xhr.status, // 响应状态码        statusText: xhr.statusText // 状态码对应的文本      })    }        xhr.send(method === 'POST' ? data : null)  })}/** * 检查字符串是否JSON文本 * @param {String} value 字符串 * @return {Boolean} 是否JSON文本 */var isJsonStr = function isJsonStr(value) {  try {    eval("(" + value + ")");    return true;  } catch (er) {    return false;  }}// module.exports = {//  service: new Service()// }var req = new Service()// var p = req.request({//   url: '/hget',//   method: 'GET',//   data: { name: 'zhangsan' }// })var p = req.request({  url: '/hput',  method: 'PUT',  data: { name: 'zhangsan' }})// var p = req.request({//   url: '/hpost',//   method: 'POST',//   data: { name: 'zhangsan' }// })p.then(res => console.log('resolved', res)).catch(err => console.log('rejected', err))