2-4、获取响应数据

2019-12-05  本文已影响0人  Eileen_1d88

上一节,我们从网络层面上获取到了服务器端的响应,但是从代码层面上来看,没有接收响应数据的代码,那么接下来我们要做的就是这一部分的工作,我们希望得到的结果是:

axios({
  method: 'post',
  url: '/base/post',
  data: {
    a: 1,
    b: 2
  }
}).then((res) => {
  console.log(res)
})

我们拿到的res对象,希望里面包括响应数据data,响应头headers,状态码status,状态说明statusText,请求配置对象config,以及请XMLHttpRequest的对象实例request。

interface AxiosResponse {
  status: number,
  statusText: string,
  config: AxiosRequestConfig,
  headers: any,
  request: any,
  data: any
}
// 当axios请求返回一个AxiosPromise,
// 那么resolve中返回的就是AxiosResponse类型的响应数据
interface AxiosPromise extends Promise<AxiosResponse> {}

对于一个ajax请求的respons,我们是可以指定它的响应数据的类型的,通过设置XMLHttpRequest对象的responseType属性,于是我们可以给AxiosRequestConfig增加一个属性responseType

interface AxiosRequestConfig {
  url: string,
  method?: Method,
  headers?: any,
  data?: any,
  params?: any,
  responseType?: XMLHttpRequestResponseType
}

responseType的类型是XMLHttpRequestResponseType类型,它的值可以是""、arraybuffer、blob、document、json、text、ms-stream 。

实现获取响应数据的逻辑

首先我们要在xhr中增加onreadystatechange事件的处理函数,并且让xhr函数返回AxiosPromise类型

import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from "./types";

export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    // method和data可能没有, 所以给出默认值
    const { url, method = 'get', data = null, headers, responseType } = config
    const request = new XMLHttpRequest()
    if (responseType) {
      request.responseType = responseType
    }
    request.open(method.toUpperCase(), url)
    request.onreadystatechange = function handleLoad() {
      // request.readyState不是4,说明请求还未返回
      if (request.readyState !== 4) {
        return
      }
      const responseHeaders = request.getAllResponseHeaders()
      const responseData = responseType && responseType !== 'text' ? request.response : request.responseText
      const response: AxiosResponse = {
        data: responseData,
        headers: responseHeaders,
        status: request.status,
        statusText: request.statusText,
        config,
        request
      }
      resolve(response)
    }
    Object.keys(headers).forEach((name) => {
      request.setRequestHeader(name, headers[name])
    })
    request.send(data)
  })
}

src/index.ts

export default function axios(config: AxiosRequestConfig): AxiosPromise {
  processConfig(config)
  return xhr(config)
}

这样,就实现了axios的promise化

编写demo
axios({
  method: 'post',
  url: '/api/base/post',
  // headers: {
  //   'content-type': 'application/json;'
  // },
  data: {
    a: 1,
    b: 2
  }
}).then((res) => {
  console.log(res)
})
axios({
  method: 'post',
  url: '/api/base/post',
  responseType: 'json',
  data: {
    a: 3,
    b: 4
  }
}).then((res) => {
  console.log(res)
})

运行demo之后,我们发现2个问题,第一是headers是json字符串,第二是第一个请求的data是json字符串。
那么接下来,我们将要对headers进行处理

上一篇下一篇

猜你喜欢

热点阅读