原生封装ajax

番外小知识:xhr的七个事件

function fetchData (params) {
  let {method,url,data,success} = params
  let xhr = null
  if ( XMLHttpRequest) {
    xhr = new XMLHttpRequest()
  } else {
    xhr = new ActiveXObject('Microsoft.XMLHTTP') // 兼容IE6以下
  }
  if (params.method === 'get' && params.data) {
    params.url + = '?' + params.data
  }
  xhr.open(params.method,params.url,true) // 开启
  // 发送请求
  if (params.method === 'get') {
    xhr.send()
  }else if (params.method === 'post') {
    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
    xhr.send(params.data);
  }
  // 等待服务器返回内容
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status === 200 ) {
        params.success && params.success(xhr.responseText)
      } else {
        alert('出错了,Err:' + xhr.status)
      }
    }
  }
}

Promise

Promise是异步编程的一种解决方案,从语法上说,Promise是一个对象,它可以获取异步操作信息。Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数,由JavaScript引擎提供,不用自己部署。then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。但是第二个参数是可选的,不一定要提供,这两个函数都接受Promise对象传出的值作为参数。

具体用法如下:

function getData (url) {
  return new Promise ((resolve,reject)=> {
    const xhr = new XMLHttpRequest ()
    xhr.open('GET',url,true)
    xhr.send()
    xhr.onload = function {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          try {
            const response = Json.parse(xhr.responseText)
            resolve(response)
          } catch (e) {
            reject(e)
          }
        } else {
          reject(new Error(xhr.status))
        }
      }
    }
  })
}
getData(url).then((response)=> {console.log(response)})

ajax到promise的进阶
应用场景:有时我们要进行彼此之间有依赖关系的异步操作,比方说有两个异步操作,当第一个异步请求成功之后才能进行第二个异步请求,原ajax的用法是层层嵌套回调,就会产生callback cell 问题,代码的可读性和维护性都很差,引入了Promise之后,将发送异步请求与数据处理分离,可以很好的解决回调的依赖问题,代码就会变得更扁平和更可读,具体详情见下面的例子:
要求:先获取姓名,再根据姓名获取手机号
原来ajax的回调写法

$.get('xxx/getUserName',{},function(data) {
  if (data.code === '0') { // 成功回调,再来获取手机号码
    $.get('xxx/getMoblie',{},function() {
    // 数据操作处理
  })
  }
})

Promise写法

var getUserName = function () {
  return new Promise(function(resolve,reject){
      $.get('xxx/getUserName',function(data){
        resolve(data)
      })
    })
}
var getMobileNumber = function (userName) {
  return new Promise(function(resolve,reject){
    if (userName) {
      $.get('xxx/getMobileNumber',funciton(data){
        resolve(data)
      })
    }
  })
}
getUserName().then(function(userName){
getMobileNumber(userName)
}).then(function(mobile){
// 数据操作处理
})

Promise到async/await的进阶
async函数返回一个Promise对象,可以使用then方法添加回调函数,当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。async函数会隐式返回一个promise,该promise的resolve的值就是函数return返回的值
上述例子,async的用法如下:

const replayRequest = async ()=> {
  const userName = await getUserName()
  const moileNumber = await getMoileNumber()
  return moileNumber
}
replayRequest()