likes
comments
collection
share

使用axios封装网络请求~

作者站长头像
站长
· 阅读数 20

网络请求的方式

传统的Ajax基于XMLHttprequest(XHR)配置和调试混乱
jQuery-Ajax为了引入ajax而引入jquery不必要
Vue-resource相对jq,Vue-resource体积小很多Vue2.0后就不更新了
Jsonp解决跨域问题
axios

jsonp:项目的部署在domain1.com服务器上,不能直接访问domain2.com服务器上的资料。这个时候,利用script标签的src来请求数据,将数据当成一个js函数来执行,并且执行过程中传入我们需要json

封装Jsonp的核心就在于监听window上的jsonp进行回调时的名称

为什么选axios?

  • 在浏览器中发送XMLHttpRequests请求
  • 在node.js中发送http请求
  • 支持Promise API
  • 拦截请求和响应
  • 转换请求和响应数据

axios基本使用

安装

npm i -s axios

引入

import axios from 'axios'

测试

axios({
	url: 'url~'
}).then(res => {
	console.log(res)
})

为什么可以用.then()?

axios函数的返回值是个Promise对象

为什么不写请求方式?

axios默认请求方式是get

测试网站httpbin.org/

测试接口url~

axios的请求方式

get

可以放参数里

也可以直接axios.get()

axios({
	url: 'url~',
    method: 'get'
}).then(res => {
	console.log(res)
})
axios.get()

带参

axios({
	url: 'url~',
}).then(res => {
	console.log(res)
})

等价于

axios({
	url: 'url~',
    // 专门针对get请求参数拼接
    params: {
        type: sell
        page: 3
    }
}).then(res => {
	console.log(res)
})

post

同理

post请求有请求体

data: {id: 2}

axios.all()

  • 返回结果是个数组
  • axios.spread可以将数组[res1,res2]展开为res1,res2

同时发送两个请求怎么办?

axios.all([axios({
    url: 'url~'
}),axios(
    url: 'url~',
    params: {
    	type: 'sell',
    	page: 3
    }
)]).then(res => {consloe.log(res)})

返回结果展开

axios.all([axios({
    url: 'url~'
}),axios(
    url: 'url~',
    params: {
    	type: 'sell',
    	page: 3
    }
)]).then(axios.spread((res1, res2) => {
    console.log(res1)
    console.log(res2)
}))

全局配置

当参数固定时,可以抽取出来全局配置

axios.defaults.baseURL = 'url~'
axios.defaults.headers.post[Content-Type] = 'application/x-www-form-urlencoded'

axios实例

const instance1 = axios.create({
    baseURL: 'url~'
})
instance1({
    url: '/home/multidata',
}).then(res => {
	console.log(res)
})

axios封装

项目根目录下新建一个network文件夹,并在该文件夹下新建一个文件request.js

// request.js
import axios from 'axios'

export function request (config, success, failure) {
  // 1.创建axios实例
  const instance = axios.create({
    baseURL: 'url~',
    timeout: 5000
  })
  // 发送真正的网络请求
  instance(config)
    .then(res => {
      success(res)
    }).catch(err => {
      failure(err)
    })
}

在需要用网络请求处

// 引入request模块
import { request } from './network/request'
request({
  url: '/home/multidata'
}, res => {
  console.log(res)
}, err => {
  console.log(err)
})

Promise方式

// request.js
import axios from 'axios'

export function request (config) {
  return new Promise((resolve, reject) => {
      // 1.创建axios实例
      const instance = axios.create({
        baseURL: 'url~',
        timeout: 5000
      })
      // 发送真正的网络请求
      instance(config)
        .then(res => {
          resolve(res)
        }).catch(err => {
          reject(err)
        })
      })
}

在需要用网络请求处

// 引入request模块
import { request } from './network/request'
request({
  url: '/home/multidata'
}).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

为什么axios.create创建出来的instance实例有.then方法?

因为这个方法创建出来的实例是Promise对象实例

所以

最终方案

// request.js
import axios from 'axios'

export function request (config) {
  // 1.创建axios实例
  const instance = axios.create({
    baseURL: 'url~',
    timeout: 5000
  })
  // 发送真正的网络请求
  return instance(config)
}

在需要用网络请求处

// 引入request模块
import { request } from './network/request'
request({
  url: '/home/multidata'
}).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

经验

组件对于第三方模块的依赖性不能太强

假如有50组件引入了axios,万一哪一天axios不维护了,那要改50个组件,这种行为很危险

但是一定要用它,怎么办?

封装成独立的模块,组件想用引入就行

当axios哪一天不维护了,也不用全部组件一个一个改

只要修改封装的那一部分代码(换成别的第三方模块)即可

axios拦截器

用于每次发送请求或得到响应之后进行相应的处理

请求拦截

请求拦截一定要返回config,不然请求发不出去啦……

请求拦截一般会有哪些操作?

  • 比如config中的一些信息不符合服务器的要求(header,当然header也可以在公共参数那里设置)
  • 比如每次发送网络请求时,都希望在界面中显示一个请求的动画或图标
  • 某些网络请求(登陆token),必须携带一些特殊信息,不然执行相关操作(如未登录跳转到登陆界面)
import axios from 'axios'

export function request (config) {
  // 1.创建axios实例
  const instance = axios.create({
    baseURL: 'url~',
    timeout: 5000
  })
  // 2.请求拦截
  instance.interceptors.request.use(config => {
    console.log(config)
    return config
  }, err => {
    console.log(err)
  })
  // 3.发送真正的网络请求
  return instance(config)
}

响应拦截

响应拦截一定要返回res,不然拿不到响应结果啦……

不过只要返回res.data就行,其信息不需要

import axios from 'axios'

export function request (config) {
  // 1.创建axios实例
  const instance = axios.create({
    baseURL: 'url~',
    timeout: 5000
  })
  // 2.响应拦截
  instance.interceptors.response.use(res => {
    console.log(config)
    return res
  }, err => {
    console.log(err)
  })
  // 3.发送真正的网络请求
  return instance(config)
}
转载自:https://juejin.cn/post/7073097106105319431
评论
请登录