前言
最近接到一个需求,登录后需要把站点id 加入到请求header 中。那么我们很容易就能想到通过用axios
的拦截器中设置就可以了,页面打开后必定会调用一个获取站点(getStation)
的接口拿到station_id
后,给其余的所有接口header 都加上 station_id
, 但问题是当打开页面的时候,页面可能会同时调用其他接口,你并不能明确知道你这个接口一定是先返回的。
思路
我们可以在没有station信息
的时候将请求加入到队列中。但是这样会reject后
控制台会Promise.reject
报错,所以这种并不合适
const queue: any[] = []
/** 是否在获取station */
function initStation() {
const STATION_URL = GetStation.url
const BLACK_URLS = [
Token.url,
]
let stationData: GetStationResponse | null = null
instance.interceptors.request.use((config) => {
if (BLACK_URLS.includes(config.url!)) {
return config
}
if (!stationData?.station) {
// eslint-disable-next-line no-new
new Promise((resolve) => {
queue.push({
config,
resolve,
})
})
return Promise.reject(config)
}
const type = stationData?.station?.type
config.headers['x-station-id'] = stationData?.station?.station_id || '0'
return config
})
instance.interceptors.response.use((response) => {
if (response.config.url?.includes(STATION_URL)) {
const json: GetStationResponse = response.data
stationData = json
queue.forEach(({ config, resolve }) => {
config.headers['x-station-id'] = json.station.station_id || '0'
resolve(instance(config))
})
}
return response
})
}
另一种方法
如果站点信息
没有值的时候,其他请求都在等待中,等getStation
返回后再回来执行其他请求
export function initStation() {
const STATION_URL = GetStation.url
const BLACK_URLS = [
Token.url,
STATION_URL,
]
let stationData: GetStationResponse | null = null
let tempResult: (res: GetStationResponse) => void
const resultPromise = new Promise<GetStationResponse>((resolve) => {
tempResult = (res: GetStationResponse) => {
stationData = res
resolve(res)
}
})
instance.interceptors.request.use((config) => {
if (BLACK_URLS.includes(config.url!)) {
return config
}
/** 如果没拿到station 数据那么就等待 */
if (!stationData?.station) {
return resultPromise.then((res) => {
config.headers['x-station-id'] = res?.station?.station_id || '0'
return config
})
}
config.headers['x-station-id'] = stationData?.station?.station_id || '0'
return config
})
instance.interceptors.response.use(
(response) => {
/** 如果当前返回了,那么执行回调 */
if (response.config.url?.includes(STATION_URL)) {
const json: GetStationResponse = response.data
tempResult(json)
}
return response
},
(error) => {
return Promise.reject(error)
},
)
}
注意事项
因为接口一直在排队,可能会造成影响,比如devtool -> network
是看不到请求的