一些基础的http对象请求配置(封装一个http在后面)
在JavaScript中,函数也是对象,可以像其他对象一样拥有属性和方法。因此,我们可以给函数添加额外的属性和方法,以扩展函数的功能。
/**
* 当你调用http.get(url, data, headers)时,实际上是调用了http函数,并传入了一个配置对象
* @param {*} url
* @param {*} headers
* @param {*} data
* @returns
*/
http.get = function (url, headers, data) {
return http({
method: 'GET',
url,
data,
headers
})
}
http.post = function (url, headers, data) {
return http({
method: 'POST',
url,
data,
headers
})
}
http.put = function (url, headers, data) {
return http({
method: 'PUT',
url,
data,
headers
})
}
http.delete = function (url, headers, data) {
return http({
method: 'DELETE',
url,
data,
headers
})
}
封装一个http函数
其中的 config 形参所接受的实参就是上述 .get 等方法传入的值
/**
* 创建一个基于 axios 和 微信小程序的封装请求组件
* @param {*} config 形参,根据传递的参数 如:{ url, methods, headers, data }
* @returns wx.request 不支持 Promise ,需要封装一个,然后返回一个 Promise
*/
function http(config) {
/**
* new 一个 Promise 实例
* resolve 和 reject 为返回的成功和失败的函数
*/
return new Promise((resolve, reject) => {
// 判断封装的 http 对象中是否存在基地址
if (http.baseURL) {
/**
* 根据获得的基地址和传递的地址来判断 2 者之间是否多出一个 '/'
*/
if (config.url.startsWith('/')) {
// startsWith (第一个字符是否是 '/'), endsWith (最后一个字符是否为 '/')
if (http.baseURL.endsWith('/')) {
// split(0, -1) (将字符串切割删除)
config.url = http.baseURL.split(0, -1) + config.url
} else {
config.url = http.baseURL + config.url
}
} else {
if (http.baseURL.endsWith('/')) {
config.url = http.baseURL + config.url
} else {
config.url = http.baseURL + '/' + config.url
}
}
}
// 调用 http 对象中的 响应拦截器 将传入的值 返回一个先的 config
config = http.interceptors.request._cb(config)
if (!config.method) {
config.method = 'GET'
}
// 如果请求头存在
if (config.headers) {
// 将其中的值传给 wx.request 中指定的值
config.header = config.headers
// 在微信中请求头的键为 header ,而 axios 中的键为 headers
// 将值传出后删除
delete config.headers
}
wx.request({
// 将 config 展开传入
...config,
// 调用成功进入的函数
success(res) {
res = http.interceptors.response._cb(res)
// 调用成功,res如果是 Promise ,在其内部会自动区分,
、等待其状态完成再执行,如果正确就返回其值,错误就进入错误的函数
resolve(res)
},
// 调用失败进入的函数
fail(err) {
err = http.interceptors.response._cb(err)
// 是错误的话,直接抛出错误
if (err instanceof Promise) {
resolve(err)
} else {
reject(err)
}
}
})
})
}
在上述中有体现到 Promise 链式调用的特性,在 new Promise((resolve, reject) => { }) 实例对象中,在resolve函数中再次调用一个Promise对象时,在其内部会自动去区分,在其状态发生改变后再去执行,成功时返回的值就是她本身的值,失败时就将其本身当做错误抛出,在reject中,同理
响应拦截器和请求拦截器
http.interceptors = {
request: {
_cb: config => config,
use(cb) {
this._cb = cb
}
},
response: {
_cb: res => res,
use(cb) {
this._cb = cb
}
}
}
其中_cb是一个函数,它接受一个配置对象 config 或者 res 作为参数,并直接返回该配置对象。这个函数的作用是将传入的配置对象原封不动地返回。
1.在请求中,需要先执行拦截器在去执行请求
2.在 use(cb)中的 cb 就是上述代码中调用成功和失败的 回调3._cb也是一个 临时的存储变量,方便使用请求拦截器和响应拦截器。