import { normalizeConfig } from './helpers' import { AjaxInstance, AjaxOption, AxiosMethods } from './types' import { cancellerCalled } from './canceller' type AnyObject = Record // GDataShape通过initAjax的第二个泛型参数传入,单独的请求如果不传返回数据的类型,则默认使用GDataShape // DataType通过ajax.get, ajax.post等方法的泛型参数传入,如果定义了这个参数,会将GDataShape覆盖 export interface RequestCreator { // request = ajax.get(url, options_1) (url: string, options?: Partial): { // request(params, options_2) (params?: AnyObject | null, opts?: Partial): Promise } } const postLikeMethods = ['PUT', 'POST', 'DELETE' , 'PATCH'] export const generateMethod = (ajax: AjaxInstance, method: AxiosMethods): RequestCreator => /** * * @param url 完整的请求url链接 * @param options ajax配置 * @returns 返回一个发送请求的函数 */ (url: string, options?: Partial) => /** * 发送请求 * @param params get类请求的url参数 or post类请求的请求体数据 * @param opts ajax参数,拥有最高优先级 * @returns 请求数据 */ async (params?: AnyObject | null, opts?: Partial) => { const mergedOptions = { ...options, ...opts } const isPostLikeMethod = postLikeMethods.includes(method) const config = { ...mergedOptions, params: isPostLikeMethod ? undefined : params, data: isPostLikeMethod ? params : undefined, url, method } // 处理取消请求逻辑 const needCancel = typeof mergedOptions.cancelKey !== 'undefined' if (needCancel) { if (typeof AbortController !== 'undefined') { // 环境支持AbortController const controller = new AbortController() config.signal = controller.signal ajax.canceller[mergedOptions.cancelKey] = () => { controller.abort.call(controller) // 删除挂载在ajax上的请求中断函数 Reflect.deleteProperty(ajax.canceller, mergedOptions.cancelKey) } } else { // 环境如果不支持AbortController,取消函数挂载到ajax只能交给adapter里面去实现了 config.signal = undefined // 默认的取消函数,因为异步的关系,逻辑可能还没走到adapter中去,取消函数就已经被调用了,此时取消函数还是undefined // 默认函数将已经调用的取消函数名称记录下来,在adapter中走到发送请求的逻辑时,直接中断即可 ajax.canceller[mergedOptions.cancelKey] = () => { cancellerCalled.push(mergedOptions.cancelKey) Reflect.deleteProperty(ajax.canceller, mergedOptions.cancelKey) } } } const finalOpts = normalizeConfig(ajax, config) // mock const mock = finalOpts.mock if (mock) { return Promise.resolve(mock) } const res = await ajax.request(finalOpts) return res }