jsonp 请求封装

再写 vue 或者 react 项目的时候,我们一般都用 axios 库进行 http 请求, 但 axios 不支持 jsonp 请求, 这里想到两个解决方案:

  1. 下载 jQuery, jQuery.ajax 支持 jsonp
  2. 自己封装一个。

我选择自己封装一个,因为为了 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)
})

参考:

使用axios发送jsonp请求

posted @ 2021-07-03 17:23  暗恋桃埖源  阅读(230)  评论(0编辑  收藏  举报