类名 common/service/FetchServer.js
import { defaultValue, isNull, Log } from '../util'
import FetchRequest from './FetchRequest'
import RequestInterceptor from './RequestInterceptor'
import ResponseInterceptor from './ResponseInterceptor'
import { TokenAttachType } from '../base/enum'
import {
  getWMSInfoFromXML,
  getDoc,
  getWMTSInfoFromXML,
  getWFSInfoFromXML,
  fromQueryResult,
  getWFSFeature,
  ServiceConfigToken,
  ServiceConfigRequestInterceptors, ServiceConfigResponseInterceptors
} from './Utils'
import { FeatureSet } from '../base'
import { SpatialReference } from '../base/geometry'
import Config from './Config'

/**
 * @private
 * @class FetchServer
 * @classdesc 对接各种服务的Service的基类。
 * @param url - {string} 服务地址。
 * @param options - {Object} 可选参数。如:
 * @param {String} [options.url = 无] 基地址,必填
 * @param {Object} [options.headers = 无] 自定义请求头参数
 * @param {Function} [options.requestInterceptor = 无] 所有请求发送前会触发的函数
 * @param {Function} [options.responseInterceptor = 无] 所有请求发送后会触发的函数
 * @param {Number} [options.requestTimeout = 45000] 请求超时时间,默认45000ms,即45s
 * @param {String} [options.tokenKey = 'token'] token名
 * @param {String} [options.tokenValue = 无] token值
 * @param {TokenAttachType} [options.tokenAttachType = TokenAttachType.url] 指定token附加到何处
 */
class FetchServer {
  constructor(url, options) {
    options = defaultValue(options, {})
    /**
     * 服务基地址
     * @member {String} FetchServer.prototype.url
     * */
    this.url = url
    /**
     * 所有请求发送前会触发的函数
     * @member {Function} FetchServer.prototype.requestInterceptor
     * */
    this.requestInterceptor = defaultValue(
      options.requestInterceptor,
      new RequestInterceptor()
    )
    /**
     * 所有请求发送后会触发的函数
     * @member {Function} FetchServer.prototype.responseInterceptor
     * */
    this.responseInterceptor = defaultValue(
      options.responseInterceptor,
      new ResponseInterceptor()
    )
    /**
     * 请求超时时间,默认45000ms,即45s
     * @member {Function} FetchServer.prototype.requestTimeout
     * */
    this.requestTimeout = defaultValue(options.requestTimeout, 45000)
    /**
     * 请求头参数
     * @member {Function} FetchServer.prototype.headers
     * */
    this.headers = defaultValue(options.headers, {})
    /**
     * token名
     * @member {Function} FetchServer.prototype.tokenKey
     * */
    this.tokenKey = defaultValue(options.tokenKey, 'token')
    /**
     * token值
     * @member {Function} FetchServer.prototype.tokenValue
     * */
    this.tokenValue = defaultValue(options.tokenValue, undefined)
    /**
     * 指定token附加到何处
     * @member {Function} FetchServer.prototype.tokenAttachType
     * */
    this.tokenAttachType = defaultValue(
      options.tokenAttachType,
      TokenAttachType.url
    )
  }

  /**
   * 销毁对象方法
   * */
  destroy() {
    this.url = null
    this.options = null
  }

  /**
   * @function  FetchServer.prototype.request
   * @description: 该方法用于向服务发送请求。
   * @param options - {Object} 参数。
   * @param {string} [options.method] 请求方式,包括"GET","POST","PUT","DELETE"。
   * @param {string} [options.url] 发送请求的地址。<br>
   * @param {String} [options.data] 发送到服务器的数据,适用于"POST"。
   * @param {Function} [options.success] 成功回调函数。
   * @param {Function} [options.failure] 失败回调函数。
   * @param {Boolean} [options.withCredentials = false] 是否携带cookie。
   */
  request(options) {
    options = defaultValue(options, {})

    // url正确性检查
    if (isNull(options.url)) {
      Log.error('url不存在!')
      return
    }

    // 执行所有请求发送前会触发的函数
    if (
      !isNull(this.requestInterceptor) &&
      !isNull(this.requestInterceptor.before) &&
      this.requestInterceptor.before instanceof Function
    ) {
      options = this.requestInterceptor.before(options)
    }

    if (!isNull(options)) {
      return this._commit(options)
    }
  }

  _commit(options) {
    const self = this
    if (options.url.indexOf('?') > -1) {
      if (options.url.indexOf('?') === options.url.length - 1) {
        options.url += `${ServiceConfigToken(Config)}`
      } else {
        options.url += `&${ServiceConfigToken(Config)}`
      }
    } else {
      if (options.method !== 'POST') {
        options.url += `?${ServiceConfigToken(Config)}`
      }
    }
    options.url = ServiceConfigRequestInterceptors(Config, options.url)
    options.headers = defaultValue(options.headers, {})
    let _headers = Object.assign(options.headers, this.headers)
    _headers = Object.assign(_headers, Config.headers)
    const _fetchOptions = {
      headers: _headers,
      withCredentials: options.withCredentials,
      requestTimeout: this.requestTimeout,
      proxy: options.proxy,
      tokenKey: this.tokenKey,
      tokenValue: this.tokenValue,
      tokenAttachType: this.tokenAttachType
    }
    if (options.responseType) {
      _fetchOptions.responseType = options.responseType
    }
    return FetchRequest.commit(
      options.method,
      options.url,
      options.data,
      _fetchOptions
    )
      .then(function (response) {
        let check
        if (response.text) {
          if (_fetchOptions.responseType === 'blob') {
            return response.blob()
          } else {
            check = () => response.text()
          }
        } else {
          check = () => response.json()
        }
        if (response.status === 200) {
          return new Promise(
            (resolve) => {
              check().then(function (text) {
                let result
                // 如果返回信息不存在
                if (isNull(text)) {
                  result = {
                    succeed: true,
                    msg: '服务器没有返回信息',
                    data: undefined
                  }
                } else {
                  let data
                  // 有返回信息,将text转为对象
                  if (typeof text === 'string') {
                    // 是xml,则解析
                    if (text.indexOf('<?xml') > -1) {
                      // 是WMS的元数据信息
                      if (
                        text.indexOf('OGC:WMS') > -1 ||
                        text.indexOf('WMS_Capabilities') > -1
                      ) {
                        // 确认服务版本号
                        let version = '1.1.1'
                        if (text.indexOf('1.3.0') > -1) {
                          version = '1.3.0'
                        }
                        // xml转dom元素
                        const xmlDoc = getDoc(text)
                        // 从dom中获取信息
                        data = getWMSInfoFromXML(xmlDoc, version)
                      } else if (
                        text.indexOf('WMTS') > -1 ||
                        text.indexOf('wmts/1.0') > -1
                      ) {
                        // 是WMTS的元数据信息
                        // xml转dom元素
                        const xmlDoc = getDoc(text)
                        // 从dom中获取信息
                        data = getWMTSInfoFromXML(xmlDoc)
                      }
                      // 取服务元信息
                      else if (text.indexOf('wfs:WFS_Capabilities') > -1) {
                        // 是WFS的元数据信息
                        // xml转dom元素
                        const xmlDoc = getDoc(text)
                        // 从dom中获取信息
                        data = getWFSInfoFromXML(xmlDoc)
                      }
                      // WFS要素查询
                      else if (text.indexOf('wfs:FeatureCollection') > -1) {
                        // 是WFS的元数据信息
                        // xml转dom元素
                        const xmlDoc = getDoc(text)
                        // 从dom中获取信息
                        data = getWFSFeature(xmlDoc)
                      } else if (text.indexOf('<svg') > -1) {
                        // 是svg,则直接返回
                        data = text
                      }
                    } else if (text.indexOf('html>') > -1) {
                      if (
                        !isNull(self.responseInterceptor) &&
                        !isNull(self.responseInterceptor.failure) &&
                        self.responseInterceptor.failure instanceof Function
                      ) {
                        self.responseInterceptor.failure({
                          succeed: false,
                          msg: `服务器不支持${options.method}请求或其他错误`,
                          data: undefined,
                          errorType: 'unKnownError'
                        })
                      }
                      if (
                        !isNull(options.failure) &&
                        options.failure instanceof Function
                      ) {
                        options.failure({
                          succeed: false,
                          msg: `服务器不支持${options.method}请求或其他错误`,
                          data: undefined,
                          errorType: 'unKnownError'
                        })
                      }
                      return Promise.reject({
                        succeed: false,
                        msg: `服务器不支持${options.method}请求或其他错误`,
                        data: undefined,
                        errorType: 'unKnownError'
                      })
                    } else {
                      data = JSON.parse(text)
                      // 基于矢量图层的要素查询,报数据转为feature
                      if (
                        data instanceof Object &&
                        (options.url.indexOf('/igs/rest/mrfs/layer/query') >
                          -1 ||
                          options.url.indexOf('/igs/rest/mrfs/docs/') > -1)
                      ) {
                        // 可以进行多GDBP的要素查询,因此返回要素集合数组
                        const featureSets = fromQueryResult(data)

                        delete data.SFEleArray
                        data.featureSets = featureSets
                        // 返回要素信息数组
                        const featureInfos = []
                        if (featureSets.length > 1) {
                          for (let i = 0; i < featureSets.length; i++) {
                            featureInfos.push(data[String(i)])
                            delete data[String(i)]
                          }
                        } else {
                          data.AttStruct.TotalCount = data.TotalCount
                          featureInfos.push(data.AttStruct)
                          delete data.AttStruct
                          delete data.TotalCount
                        }
                        data.featureInfos = featureInfos
                        if (
                          options.url.indexOf('/igs/rest/mrfs/docs/') > -1 ||
                          options.url.indexOf('/igs/rest/mrfs/layer/') > -1
                        ) {
                          if (featureSets.length > 0) {
                            data.featureSet = featureSets[0]
                          } else {
                            data.featureSet = new FeatureSet()
                          }
                        }
                      }
                    }
                  }
                  // 如果不是对象,直接返回信息
                  if (!(data instanceof Object)) {
                    result = {
                      succeed: true,
                      msg: data,
                      data
                    }
                  } else {
                    // 数据里面有features属性且为数组,且里面的是一个要素
                    if (
                      data.hasOwnProperty('features') &&
                      data.features instanceof Array
                    ) {
                      // 解析服务内坐标信息
                      let spatialReference = new SpatialReference('EPSG:4326')
                      if (data.spatialReference) {
                        spatialReference = SpatialReference.fromJSON(
                          data.spatialReference
                        )
                      }

                      const reg = /(igs)\/rest\/services\/.*\/WFSServer/
                      let reverse = false
                      // 是否对数据反转
                      if (
                        reg.test(options.url) &&
                        spatialReference.wkid === 4326
                      ) {
                        reverse = true
                      }
                      // 转成要素基本对象
                      data.featureSet = FeatureSet.fromArray(
                        data.features,
                        new FeatureSet({
                          spatialReference
                        }),
                        {
                          reverse
                        }
                      )
                    } else if (
                      options.url.indexOf('/MapServer/query') > -1 ||
                      options.url.indexOf('/SceneServer/query') > -1
                    ) {
                      if (data.layers && data.layers instanceof Array) {
                        // 解析服务内坐标信息
                        let spatialReference = new SpatialReference('EPSG:4326')
                        if (data.spatialReference) {
                          spatialReference = new SpatialReference({
                            wkid: data.spatialReference.wkid,
                            wkt: data.spatialReference.wkt
                          })
                        }
                        const layers = data.layers
                        for (let i = 0; i < layers.length; i++) {
                          if (layers[i].features) {
                            layers[i].featureSet = FeatureSet.fromArray(
                              layers[i].features,
                              new FeatureSet({ spatialReference })
                            )
                            delete layers[i].features
                          }
                        }
                      }
                    }
                    // 查询图层列表信息
                    else if (options.url.indexOf('/MapServer/layers?') > -1) {
                      function _setLayersId(layers) {
                        for (let i = 0; i < layers.length; i++) {
                          layers[i].id = layers[i].index
                          if (
                            layers[i].children &&
                            layers[i].children instanceof Array
                          ) {
                            _setLayersId(layers[i].children)
                          }
                        }
                      }
                      _setLayersId(data.layers)
                    }
                    result = {
                      succeed: true,
                      msg: '请求成功',
                      data
                    }
                  }
                }

                // 执行config的after方法
                result = ServiceConfigResponseInterceptors(
                  Config,
                  options.url,
                  result
                )

                // 执行请求响应,接口调用成功时会执行的回调
                if (
                  !isNull(self.responseInterceptor) &&
                  !isNull(self.responseInterceptor.success) &&
                  self.responseInterceptor.success instanceof Function
                ) {
                  result = self.responseInterceptor.success(result)
                }

                // 有成功回调函数,则执行
                if (
                  !isNull(result) &&
                  !isNull(options.success) &&
                  options.success instanceof Function
                ) {
                  options.success(result)
                }
                resolve(result)
              })
            },
            (reject) => {
              console.log('Fetch返回异常', reject)
            }
          )
        } else {
          return new Promise(
            (resolve) => {
              check().then(function (text) {
                let result
                // 如果返回信息不存在,则返回请求失败
                if (isNull(text)) {
                  result = {
                    succeed: false,
                    msg: '请求失败,服务器没有返回信息',
                    data: undefined
                  }
                } else {
                  // 有返回信息,将text转为对象
                  const data = JSON.parse(text)
                  // 如果不是对象,直接返回信息
                  if (!(data instanceof Object)) {
                    result = {
                      succeed: false,
                      msg: data,
                      data: undefined
                    }
                  } else {
                    result = {
                      succeed: false,
                      msg: '请求失败',
                      data
                    }
                  }
                }

                // 请求响应成功,接口调用失败时会执行的函数
                if (
                  !isNull(self.responseInterceptor) &&
                  !isNull(self.responseInterceptor.failure) &&
                  self.responseInterceptor.failure instanceof Function
                ) {
                  result = self.responseInterceptor.failure(result)
                }

                // 当failure回调存在,则运行failure
                if (
                  !isNull(result) &&
                  !isNull(options.failure) &&
                  options.failure instanceof Function
                ) {
                  options.failure(result)
                }
                resolve(result)
              })
            },
            (reject) => {
              console.error('Fetch返回异常', reject)
            }
          )
        }
      })
      .catch(function (error) {
        // 执行所有请求发送失败后触发的函数
        if (
          !isNull(self.requestInterceptor) &&
          !isNull(self.requestInterceptor.failure) &&
          self.requestInterceptor.failure instanceof Function
        ) {
          self.requestInterceptor.failure(error)
        }
      })
  }
}

export default FetchServer
构造函数
成员变量
方法
事件