preface
最近在寫 react 項目, 然後調用後臺接口的時候總是報錯, 我本以爲是後臺接口的問題
後來後臺說 請求體 不能爲 null
然後就簡單做了總結
請求頭 content-type 一般使用的兩種格式
application/json
在該種格式情況下, 請求體不能爲 null , 應是一個 json 字符串, 如果沒有數據就加一個 {}
吧
因爲最近一直在開發小程序, 應該是底層做了處理, 所以 同樣的情況,沒有報錯,導致出現問題,一時間沒有反應過來
application/www-from-urlencoded
post 請求 queryString 的方式, 請求頭爲該類型
封裝請求 實戰
一般默認的 content-type application/json
axios
- 默認的 content-type application/json
- 我們在使用 axios 的時候,可以在導航守衛中 判斷 params 是否存在, 存在則修改請求頭 爲 www-form-urlencoded
下面是封裝的 axios 請求
import axios, { AxiosRequestConfig } from 'axios'
import { baseURL, TokenName } from '@/constants'
import { getToken } from '@/utils'
import { Toast, Dialog } from 'vant'
class RequestError extends Error {
public msg: string
public code: string
public statusCode: number
public name: string
public constructor(statusCode: number, code: string, msg: string) {
super()
this.msg = msg
this.code = code
this.statusCode = statusCode
this.name = 'RequestError'
}
}
function unAuthTologin(): void {
// 跳轉到某個頁面即可
}
function defaultHandler(reqError: RequestError) {
let msg = reqError.msg
if (!msg) {
switch (reqError.statusCode) {
case 400: msg = '請求錯誤(400)'; break
case 401:
msg = '授權已經失效,請重新掃碼領券!'
// unAuthTologin()
break
case 403: msg = '拒絕訪問(403)'; break
case 404: msg = '請求出錯(404)'; break
case 408: msg = '請求超時(408)'; break
case 500: msg = '服務器錯誤(500)'; break
case 501: msg = '服務未實現(501)'; break
case 502: msg = '網絡錯誤(502)'; break
case 503: msg = '服務不可用(503)'; break
case 504: msg = '網絡超時(504)'; break
case 505: msg = 'HTTP版本不受支持(505)'; break
default: msg = `連接出錯(${reqError.statusCode})!`
}
}
// 錯誤提示
Dialog.alert({
title: '提示',
message: msg
})
// Message.error({ message: msg })
}
const service = axios.create({
baseURL,
timeout: 2000,
method: 'POST' // 默認 post 請求
})
service.interceptors.request.use((config: AxiosRequestConfig) => {
const token = getToken()
token && (config.headers[TokenName] = token)
config.__loading = config.__loading || true
if (config.method === 'post') {
config.headers['content-type'] && !config.data && (config.data = {})
config.params && !config.headers['content-type'] && (config.headers['content-type'] = 'application/x-www-form-urlencoded')
}
if (config.__loading) { // 默認加載 loading
// loading 效果
config.__toast = Toast.loading({
message: '加載中...',
forbidClick: true,
loadingType: 'spinner'
})
}
// !config.loading
// headers: { 'content-type': 'application/x-www-form-urlencoded' },
// 1. token
// 2. loading
// 3. application/json
// 4. params 處理
return config
}, (error) => {
console.log('error--', error)
return Promise.reject(error)
})
service.interceptors.response.use(({ config, data }) => {
config.__toast && config.__toast.close()
const { retCode, retMsg } = data
if (!config.businessErrNotTip && retCode && retCode !== '000000') {
// 錯誤提示
Dialog.alert({
title: '提示',
message: retMsg,
confirmButtonColor: ''
})
return Promise.reject(data)
}
return Promise.resolve(data)
}, ({ response, msg: resMsg, config }) => {
config.__toast && config.__toast.close()
let msg = ''
let code = '-1'
let statusCode
if (response && response instanceof Object) {
const { msg: errMsg, code: errCode } = response.data // 這裏字段可能需要修改
statusCode = response.status
code = errCode
msg = errMsg
} else {
statusCode = 600
msg = resMsg || 'Network Error'
}
const wrapError = new RequestError(statusCode, code, msg)
defaultHandler(wrapError)
return Promise.reject(wrapError)
})
export default service
其中處理了 post 方法 content-type 問題
if (config.method === 'post') {
config.headers['content-type'] && !config.data && (config.data = {})
config.params && !config.headers['content-type'] && (config.headers['content-type'] = 'application/x-www-form-urlencoded')
}
小程序的請求
- 默認的 content-type application/json
- params 存在,存在則修改請求頭 爲 www-form-urlencoded
在寫小程序代碼過程中發現這個問題貌似框架幫忙處理了。