hailu
2023-05-25 3644568ac3b6db7e387d5ab72da717e51626f869
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import InterceptorManager from './InterceptorManager'
import RequestConstructor from '../adapters/Request'
import buildURL from '../helpers/buildURL'
import detachConfig from '../helpers/detachConfig'
import mergeConfig from '../helpers/mergeConfig'
import dispatchRequest from './dispatchRequest'
import { detachCancel, dispatchCancel, interceptCancel } from './handleCancel'
import defaults, { METHOD } from '../defaults'
import { forEach, merge } from '../utils'
 
export default function Ajax(defaultConfig) {
  // 挂载当前实例配置
  const config = typeof defaultConfig === 'object' ? merge(defaultConfig) : defaultConfig
  ajax.config = Object.freeze(config)
 
  // 挂载全局默认配置引用
  ajax.defaults = defaults
 
  // 挂载拦截器
  ajax.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  }
 
  // 挂载获取实例请求地址方法
  ajax.getURL = async function getURL(config) {
    const combineConfig = await mergeConfig(defaults, defaultConfig, config)
    return buildURL(combineConfig).replace(/^\?/, '')
  }
 
  // 挂载对应的 method 方法
  forEach(METHOD, method => {
    ajax[method] = function (url, data, config) {
      if (typeof url === 'string') return ajax(url, data, { ...config, method })
      return ajax({ ...url, method })
    }
  })
 
  function ajax(...args) {
    // 分类请求参数
    const { callback, config } = detachConfig(...args)
 
    // 创建请求类
    const Request = RequestConstructor()
 
    // 声明 Promise 链
    const chain = [dispatchRequest(Request), dispatchCancel]
 
    // 将请求拦截遍历添加到链前面
    ajax.interceptors.request.forEach.desc(({ fulfilled, rejected }) =>
      chain.unshift(fulfilled, rejected)
    )
 
    // 将响应拦截遍历添加到链后面
    ajax.interceptors.response.forEach.asc(({ fulfilled, rejected }) =>
      chain.push(fulfilled, interceptCancel(rejected))
    )
 
    // 先执行获取 config 请求配置
    chain.unshift(config => mergeConfig(defaults, defaultConfig, config), undefined)
 
    // 处理发起请求前的错误数据
    chain.push(undefined, detachCancel)
 
    // 调用请求方法后,且拦截器触发完成后,判断回调参数的执行
    chain.push(
      response => {
        if (!callback) return response
        callback.success?.(response)
        callback.complete?.(response)
      },
      error => {
        if (!callback) return Promise.reject(error)
        callback.fail?.(error)
        callback.complete?.(error)
      }
    )
 
    // 创建请求Promise,遍历链将链上方法传递到then回调
    let request = Request.resolve(config)
    while (chain.length) {
      request = request.then(chain.shift(), chain.shift())
    }
 
    return request
  }
 
  return ajax
}