import { Zondy } from '../base'
import { deepClone, defaultValue, getGUID, Log } from '../util'
import { FetchMethod, TokenAttachType } from '../base/enum'
import RequestInterceptor from './RequestInterceptor'
import ResponseInterceptor from './ResponseInterceptor'
import FetchServer from './FetchServer'
import { checkParam, checkPathParameters, formatBaseUrl } from './Utils'
/**
* 服务查询基类
* @class BaseServer
* @moduleEx ServiceModule
* @param {Object} options 构造参数
* @param {String} [options.url = 无] 基地址,必填
* @param {Object} [options.headers = 无] 自定义请求头参数
* @param {String} [options.tokenKey = 'token'] token名
* @param {String} [options.tokenValue = 无] token值
* @param {TokenAttachType} [options.tokenAttachType = TokenAttachType.url] 指定token附加到何处
* @param {RequestInterceptor} [options.requestInterceptor = 无] 请求发送拦截器
* @param {ResponseInterceptor} [options.responseInterceptor = 无] 请求响应拦截器
* @param {Number} [options.requestTimeout = 45000] 请求超时时间,默认45000ms,即45s
*/
class BaseServer {
constructor(options) {
options = defaultValue(options, {})
/**
* 服务基地址
* @member {String} BaseServer.prototype.url
* @example
* //设置请求基地址
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* // ES6引入方式
* import { BaseServer } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //请求基地址
* url: '你的URL'
* });
* //动态修改
* BaseServer.url = '新URL';
*/
this.url = defaultValue(options.url, '')
const _urlObj = formatBaseUrl(this.url)
// 获取纯粹的基地址
this._url = _urlObj.baseUrl
// 保存?之后的部分
this._paramString = _urlObj.paramString ? `${_urlObj.paramString}&` : ''
/**
* 是否使用确据唯一的fetch对象,默认为true,当设为false时,会使用自己私有的fetch对象,所有的请求设置不会影响全局
* @member {Boolean} BaseServer.prototype.enableGlobeFetch
* @example
* //设置请求基地址
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* // ES6引入方式
* import { BaseServer } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //请求基地址
* url: '你的URL',
* //使用私有的fetch对象
* enableGlobeFetch: false,
* //此时设置token等属性,不会影响全局的fetch对象
* tokenValue: '你的token'
* });
* //继续使用全局fetch
* BaseServer.enableGlobeFetch = true;
*/
this.enableGlobeFetch = defaultValue(options.enableGlobeFetch, true)
/**
* 客户端id
* @member {Boolean} BaseServer.prototype.clientId
*/
this.clientId = defaultValue(options.clientId, getGUID())
// 私有变量
// 所有请求发送前会触发的函数
this._requestInterceptor = defaultValue(
options.requestInterceptor,
new RequestInterceptor()
)
// 所有请求发送后会触发的函数
this._responseInterceptor = defaultValue(
options.responseInterceptor,
new ResponseInterceptor()
)
// 请求超时时间
this._requestTimeout = defaultValue(options.requestTimeout, 45000)
// 请求头参数
this._headers = defaultValue(options.headers, undefined)
// token名
this._tokenKey = defaultValue(options.tokenKey, 'token')
// token值
this._tokenValue = defaultValue(options.tokenValue, undefined)
// 指定token附加到何处
this._tokenAttachType = defaultValue(
options.tokenAttachType,
TokenAttachType.url
)
// 私有的fetch对象
this._fetchService = undefined
// 保存公有fetch的构造参数
if (this.enableGlobeFetch) {
this._globeOptions = {
requestInterceptor: this._requestInterceptor,
responseInterceptor: this._responseInterceptor,
requestTimeout: this._requestTimeout,
headers: this._headers,
tokenKey: this._tokenKey,
tokenValue: this._tokenValue,
tokenAttachType: this._tokenAttachType,
fetchService: this._fetchService
}
} else {
// 保存私有fetch的构造参数
this._privateOptions = {
requestInterceptor: this._requestInterceptor,
responseInterceptor: this._responseInterceptor,
requestTimeout: this._requestTimeout,
headers: this._headers,
tokenKey: this._tokenKey,
tokenValue: this._tokenValue,
tokenAttachType: this._tokenAttachType,
fetchService: this._fetchService
}
}
// 初始化fetch对象
this._initFetch()
}
/**
* 获取服务信息,IGS2.0新增服务
* @param options 查询参数
* @param {Function} [options.success = 无] 查询成功回调函数,若使用Promise方式则不必填写
* @param {Function} [options.failure = 无] 查询失败回调函数,若使用Promise方式则不必填写
* @example <caption><h5>获取服务信息-回调方式</h5></caption>
* server.queryServerInfo({
* success: function (result) {
* console.log('请求成功:', result);
* },
* failure: function (result) {
* console.log('请求失败:', result);
* }
* });
*
* @example <caption><h5>获取服务信息-promise方式</h5></caption>
* server.queryServerInfo({
* })
* .then(function (result) {
* console.log('请求成功:', result);
* }).catch(function (result) {
* console.log('请求失败:', result);
* });
*/
queryServerInfo(options) {
const self = this
return this._querySimpleInfo(options, function (url) {
// igs1.0的地图服务
if (url.indexOf('/igs/rest/mrcs/docs/') > -1) {
// 拼装返回基地址,必须这样传,否则返回的数据是空的
return `${url.replace('mrcs/docs', 'mrms/info')}?f=json`
}
if (url.indexOf('/igs/rest/mrms/docs/') > -1) {
// 拼装返回基地址,必须这样传,否则返回的数据是空的
return `${url.replace('docs', 'info')}?f=json`
}
if (url.indexOf('/igs/rest/mrms/tile/') > -1) {
// 拼装返回基地址,必须这样传,否则返回的数据是空的
return `${url.replace('tile', 'info')}?f=json`
}
// igs1.0的G3D服务
if (url.indexOf('/igs/rest/g3d/') > -1) {
// 拼装返回基地址
return `${url}/GetDocInfo`
}
// 拼装返回基地址
return `${url}?f=json${self._paramString}`
})
}
/**
* 初始化并分会Fetch对象
* @private
* @return Object Fetch对象
* */
_initFetch() {
// 当全局对象不存在时,创建一个
if (this.enableGlobeFetch && !Zondy.Service._fetchService) {
// 如果有共有参数,就在初始化时赋予
if (this._globeOptions) {
Zondy.Service._fetchService = new FetchServer('', this._globeOptions)
} else {
Zondy.Service._fetchService = new FetchServer('', {})
}
} else if (!this.enableGlobeFetch && !this._fetchService) {
// 当私有对象不存在时,创建一个,如果有私有有参数,就在初始化时赋予
if (this._privateOptions) {
this._fetchService = new FetchServer('', this._privateOptions)
} else {
this._fetchService = new FetchServer('', {})
}
}
return this.enableGlobeFetch
? Zondy.Service._fetchService
: this._fetchService
}
/**
* 获取公有或私有的fetch对象
* @private
* @return Object Fetch对象
* */
_getFetch() {
// 获取fetch
let fetchService = this.enableGlobeFetch
? Zondy.Service._fetchService
: this._fetchService
// 确保fetch存在
if (!fetchService) {
fetchService = this._initFetch()
}
return fetchService
}
/**
* 发起GET请求
* @private
* @param url 查询链接
* @param options 查询参数
* */
_getRequest(url, options) {
Log.info('请求链接:', url)
Log.info('请求参数:', options)
// 成功回调函数
const success = defaultValue(options.success, undefined)
// 失败回调函数
const failure = defaultValue(options.failure, undefined)
// 发起请求
const fetchService = this._getFetch()
return fetchService.request({
url,
method: 'GET',
success(result) {
if (result) {
if (success) success(result)
}
},
failure(result) {
if (failure) failure(result)
}
})
}
/**
* 发起POST请求
* @private
* @param url 查询链接
* @param options 查询参数
* */
_postRequest(url, options) {
return this._sendBodyRequest('POST', url, options)
}
/**
* 发起DELETE请求
* @private
* @param url 查询链接
* @param options 查询参数
* */
_deleteRequest(url, options) {
return this._sendBodyRequest('DELETE', url, options)
}
/**
* 发起PUT请求
* @private
* @param url 查询链接
* @param options 查询参数
* */
_putRequest(url, options) {
return this._sendBodyRequest('PUT', url, options)
}
/**
* 发起PATCH请求
* @private
* @param url 查询链接
* @param options 查询参数
* */
_patchRequest(url, options) {
return this._sendBodyRequest('PATCH', url, options)
}
/**
* 发起所有body请求
* @private
* @param method 方法名
* @param url 查询链接
* @param options 查询参数
* */
_sendBodyRequest(method, url, options) {
// 成功回调函数
const success = defaultValue(options.success, undefined)
// 失败回调函数
const failure = defaultValue(options.failure, undefined)
// post请求发送的数据
const data = defaultValue(options.data, {})
// 设置headers
const headers = defaultValue(options.headers, undefined)
const responseType = defaultValue(options.responseType, undefined)
// 发起请求
const fetchService = this._getFetch()
return fetchService.request({
url,
method,
data,
headers,
responseType,
success(result) {
if (result) {
if (success) success(result)
}
},
failure(result) {
if (failure) failure(result)
}
})
}
/**
* 设置fetch的属性
* @private
* @param {String} key 属性名
* @param {String} value 属性值
* */
_setFetchValue(key, value) {
// 使用全局或私有fetch
if (this.enableGlobeFetch && Zondy.Service._fetchService) {
Zondy.Service._fetchService[key] = value
} else if (!this.enableGlobeFetch) {
Zondy.Service._fetchService[key] = value
}
}
/**
* 验证正确性并发送请求
* @private
* @param {Object} checkResult 校验对象
* @param {String} url 请求基地址
* @param {Object} options 额外参数
* */
_checkAndRequest(checkResult, url, options) {
options = defaultValue(options, {})
// 只有校验通过才会发送请求
if (checkResult.isChecked) {
// 发起查询
const method = defaultValue(options.method, FetchMethod.get)
switch (method) {
case FetchMethod.get:
return this._getRequest(url + checkResult.queryString, options)
case FetchMethod.post:
const postOpts = deepClone(options)
postOpts.data = checkResult.queryString
return this._postRequest(url, postOpts)
case FetchMethod.delete:
const deleteOpts = deepClone(options)
deleteOpts.data = checkResult.queryString
return this._deleteRequest(url, deleteOpts)
case FetchMethod.put:
const putOpts = deepClone(options)
putOpts.data = checkResult.queryString
return this._putRequest(url, putOpts)
default:
return this._getRequest(url + checkResult.queryString, options)
}
} else {
if (
this.requestInterceptor &&
this.requestInterceptor.failure &&
this.requestInterceptor.failure instanceof Function
) {
this.requestInterceptor.failure({
succeed: false,
msg: checkResult.errorMessage,
errorType: checkResult.errorType,
data: undefined
})
}
if (options.failure && options.failure instanceof Function) {
options.failure({
succeed: false,
msg: checkResult.errorMessage,
errorType: checkResult.errorType,
data: undefined
})
}
return Promise.reject({
succeed: false,
msg: checkResult.errorMessage,
data: undefined,
errorType: checkResult.errorType
})
}
}
/**
* 验证所有PathParameter参数的正确性,PathParameter里的参数都是必填参数,必须验证正确性
* @private
* @param {Object} options 请求参数对象
* @param {Object} checkOptions 验证对象
* @return {Boolean} 是否验证通过
* */
_checkPathParameters(options, checkOptions) {
// 默认只检测layerId
checkOptions = defaultValue(checkOptions, {
layerId: {
type: 'String'
}
})
const checkResult = checkPathParameters(checkOptions, options)
// 验证失败,调用请求拦截器失败方法
if (!checkResult.isChecked) {
if (
this.requestInterceptor &&
this.requestInterceptor.failure &&
this.requestInterceptor.failure instanceof Function
) {
this.requestInterceptor.failure({
succeed: false,
msg: checkResult.errorMessage,
errorType: checkResult.errorType,
data: undefined
})
}
return {
succeed: false,
msg: checkResult.errorMessage,
errorType: checkResult.errorType
}
}
return {
succeed: true
}
}
/**
* 进行简单的info查询,没有任何条件
* @private
* @param {Object} options 查询参数
* @param {Function} callback 处理请求基地址的回调
* @return {Boolean} 是否验证通过
* */
_querySimpleInfo(options, callback) {
options = defaultValue(options, {})
if (callback && callback instanceof Function) {
// 获取url
const url = callback(this._url) + this._paramString
// 请求方式为GET
options.method = FetchMethod.get
Log.info('发起请求,基地址为:', url)
return this._checkAndRequest(
{
isChecked: true,
errorMessage: '',
errorType: '',
queryString: ''
},
url,
options
)
}
return false
}
/**
* 通过layerId查询信息
* @private
* @param {Object} options 查询参数
* @param {Function} callback 处理请求基地址的回调
* @return {Boolean} 是否验证通过
* */
_queryInfoByLayerId(options, callback) {
options = defaultValue(options, {})
// 检查PathParameters参数
const checkPath = this._checkPathParameters(options)
if (!checkPath.succeed) {
if (options.failure && options.failure instanceof Function) {
options.failure({
succeed: false,
msg: checkPath.msg,
data: undefined
})
}
return Promise.reject({
succeed: false,
msg: checkPath.msg,
data: undefined
})
}
if (callback && callback instanceof Function) {
// 获取url
const url = callback(this._url, options)
// 请求方式为GET
options.method = FetchMethod.get
Log.info('发起请求,基地址为:', url)
return this._checkAndRequest(
{
isChecked: true,
errorMessage: '',
errorType: '',
queryString: ''
},
url,
options
)
}
}
/**
* 根据接口的PATH PARAMETERS和QUERY PARAMETERS来发起查询
* @private
* @param {Object} options 查询参数
* @param {Object} pathCheck 要检查的路径参数
* @param {Object} queryCheck 要检查的查询参数
* @param {Function} callback 处理请求基地址的回调
* @return {Boolean} 是否验证通过
* */
_queryByParameters(options, pathCheck, queryCheck, callback) {
options = defaultValue(options, {})
// 检查PathParameters参数
const checkPath = this._checkPathParameters(options, pathCheck)
if (!checkPath.succeed) {
if (options.failure && options.failure instanceof Function) {
options.failure({
succeed: false,
msg: checkPath.msg,
data: undefined,
errorType: checkPath.errorType
})
}
return Promise.reject({
succeed: false,
msg: checkPath.msg,
data: undefined,
errorType: checkPath.errorType
})
}
if (callback && callback instanceof Function) {
// 获取url
const url = callback(this._url, options)
// url += `&clientId=${this.clientId}`
Log.info('发起请求,基地址为:', url)
return this._checkAndRequest(
checkParam(options, queryCheck),
url,
options
)
}
}
}
Object.defineProperties(BaseServer.prototype, {
/**
* 请求发送拦截器
* @member {Function} BaseServer.prototype.requestInterceptor
* @example
* //设置拦截器,任何一个继承自BaseServer的对象都可以设置,全局唯一
* // ES5引入方式
* const { BaseServer,RequestInterceptor } = Zondy.Service
* // ES6引入方式
* import { BaseServer,RequestInterceptor } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //设置请求发送拦截器
* requestInterceptor: new RequestInterceptor({
* //请求发送前进行统一处理
* before: function(config) {
* //执行你的业务逻辑
* //注意必须显示返回config对象,如果返回为空,则不发送请求
* return config;
* },
* //请求发送失败时进行统一处理
* failure: function(error) {
* //执行你的业务逻辑
* }
* })
* });
* //动态修改
* BaseServer.requestInterceptor.before = function() {};
* */
requestInterceptor: {
configurable: false,
get() {
return this._requestInterceptor
},
set(value) {
// 设置fetch属性
this._setFetchValue('requestInterceptor', value)
this._requestInterceptor = value
}
},
/**
* 请求响应拦截器
* @member {Function} BaseServer.prototype.responseInterceptor
* @example
* //设置拦截器,任何一个继承自BaseServer的对象都可以设置,全局唯一
* // ES5引入方式
* const { BaseServer,ResponseInterceptor } = Zondy.Service
* // ES6引入方式
* import { BaseServer,ResponseInterceptor } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //设置请求响应拦截器
* responseInterceptor: new ResponseInterceptor({
* //执行请求响应,接口调用成功时会执行的回调
* success: function(result) {
* //执行你的业务逻辑
* //注意必须显示返回result对象,如果返回为空,则不执行请求响应成功回调
* return result;
* },
* //请求响应成功,接口调用失败时会执行的函数
* failure: function(result) {
* //执行你的业务逻辑
* //注意必须显示返回result对象,如果返回为空,则不执行回调韩式
* return result;
* }
* })
* });
* //动态修改
* BaseServer.responseInterceptor.success = function() {};
* */
responseInterceptor: {
configurable: false,
get() {
return this._responseInterceptor
},
set(value) {
// 设置fetch属性
this._setFetchValue('responseInterceptor', value)
this._responseInterceptor = value
}
},
/**
* 请求超时时间,默认45000ms,即45s
* @member {String} BaseServer.prototype.requestTimeout
* @example
* //设置超时时间
* //初始化AddressServer服务对象
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* // ES6引入方式
* import { BaseServer } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //超时时间
* requestTimeout: 2000
* });
* //动态修改
* BaseServer.requestTimeout = 3000;
* */
requestTimeout: {
configurable: false,
get() {
return this._requestTimeout
},
set(value) {
// 设置fetch属性
this._setFetchValue('requestTimeout', value)
this._requestTimeout = value
}
},
/**
* 请求头参数
* @member {String} BaseServer.prototype.headers
* @example
* //设置请求头参数
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* // ES6引入方式
* import { BaseServer } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //请求头
* headers: {
* //设置Content-Type为multipart/form-data
* 'Content-Type': 'multipart/form-data',
* //设置token
* 'token': '你的token'
* }
* });
* //动态修改
* BaseServer.headers.token = '新token';
* */
headers: {
configurable: false,
get() {
return this._headers
},
set(value) {
// 设置fetch属性
this._setFetchValue('headers', value)
this._headers = value
}
},
/**
* token名
* @member {String} BaseServer.prototype.tokenKey
* @example
* //设置token名
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* // ES6引入方式
* import { BaseServer } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //token名
* tokenKey: '你的tokenKey'
* });
* //动态修改
* BaseServer.tokenKey = '新tokenKey';
* */
tokenKey: {
configurable: false,
get() {
return this._tokenKey
},
set(value) {
// 设置fetch属性
this._setFetchValue('tokenKey', value)
this._tokenKey = value
}
},
/**
* token值
* @member {String} BaseServer.prototype.tokenValue
* @example
* //设置token值
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* // ES6引入方式
* import { BaseServer } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //token值
* tokenValue: '你的token值'
* });
* //动态修改
* BaseServer.tokenValue = '新token值';
* */
tokenValue: {
configurable: false,
get() {
return this._tokenValue
},
set(value) {
// 设置fetch属性
this._setFetchValue('tokenValue', value)
this._tokenValue = value
}
},
/**
* 指定token附加到何处
* @member {TokenAttachType} BaseServer.prototype.tokenAttachType
* @example
* //设置token值
* // ES5引入方式
* const { BaseServer } = Zondy.Service
* const { TokenAttachType } = Zondy.Enum
* // ES6引入方式
* import { BaseServer,TokenAttachType } from "@mapgis/webclient-common"
* let BaseServer = new BaseServer({
* //token名
* tokenValue: '你的token值',
* //token值
* tokenValue: '你的token值',
* //指定token附加到url后面
* tokenAttachType: TokenAttachType.url
* });
* //动态修改
* BaseServer.tokenAttachType = TokenAttachType.header;
* */
tokenAttachType: {
configurable: false,
get() {
return this._tokenAttachType
},
set(value) {
// 设置fetch属性
this._setFetchValue('tokenAttachType', value)
this._tokenAttachType = value
}
}
})
Zondy.Service.BaseServer = BaseServer
export default BaseServer