再写 vue
或者 react
项目的时候,我们一般都用 axios
库进行 http
请求, 但 axios
不支持 jsonp
请求, 这里想到两个解决方案:
- 下载
jQuery
,jQuery.ajax
支持jsonp
。 - 自己封装一个。
我选择自己封装一个,因为为了 jsonp
请求,再从下载一个 jQuery
感觉大了。
封装的 JSONP client
class JSONP {
/**
*
* @param config 配置
* @param config.timeout 超时时间
* @param config.callbackLabel 传给后台的 callback key 优先级小于 get 方法的 options.callbackLabel
*/
constructor(config = {}) {
this._reqFlag = 0 // 用来给每个jsop 请求添加唯一标识
this.timeout = config.timeout ?? 10 * 1000
this.callbackLabel = config.callbackLabel ?? 'callback' // 传给后台的 callback key
}
/**
* jsonp 请求
* @param url
* @param [options = {}]
* @param {string} [options.callbackLabel = 'callback'] 传给后台的 callback key, 优先级大于 config.callbackLabel
* @return {Promise<{id: number, name: string}[]>}
*/
get(url, options = {}) {
const callbackLabel = options.callbackLabel ?? this.callbackLabel
const jsonpCallbackFnName = 'jsonpCallback' + this._reqFlag
this._reqFlag++
const urlObj = new URL(url)
// https://fts.jd.com/area/get?fid=0&callback=aaa
const fullUrl = url + (urlObj.search ? '&' : '?') + callbackLabel + '=' + jsonpCallbackFnName
return new Promise((resolve, reject) => {
const jsonpScript = document.createElement('script')
jsonpScript.id = jsonpCallbackFnName
jsonpScript.src = fullUrl
window[jsonpCallbackFnName] = (result) => {
document.getElementById(jsonpCallbackFnName) && document.body.removeChild(jsonpScript)
resolve(result)
delete window[jsonpCallbackFnName]
}
document.body.appendChild(jsonpScript)
setTimeout(() => {
document.getElementById(jsonpCallbackFnName) && document.body.removeChild(jsonpScript)
reject(`TIMEOUT: ${this.timeout} ms 内没有响应`)
delete window[jsonpCallbackFnName]
}, this.timeout)
})
}
static create(config) {
return new JSONP(config)
}
}
export default JSONP
使用方法
以这个 jsop
接口为例 https://fts.jd.com/area/get?fid=0&callback=aaa
import JSONP from 'yourPath/jsonp'
const jsonpInstance = JSONP.create({timeout: 5 * 1000, callbackLabel: 'callback'})
function getArea(id = 0) {
return jsonpInstance.get('https://fts.jd.com/area/get?fid=' + id)
}
getArea(0).then(res => {
console.log('响应结果', res)
})
参考: