@前端拦截器-如何在微信小程序里面实现一个拦截器

406 阅读3分钟

需求

  1. 拦截请求
  2. 转换请求数据
  3. 转换响应数据
  4. 请求头的改写
  5. 添加拦截锁定期
  6. 支持拦截器内部异步处理

promise 的基础知识

  1. promise的then方法,then 的第一个执行器里面返回值的可能请求
  • 没有返回值
  • 返回值是为 ReturnPromise 对象,在下一个 then 的时候,第一个执行器的参数是 上一个 ReturnPromise 的 resolve 或者 reject 的值。
  • 返回值不是promise,是数据类型,下一个then函数的第一个执行器的参数能,拿到的就是这数据
  • promise 的value 是内部数据类型,只能在then中拿到,外部是拿不到的
  • 我们要在then实现异步任务,现在做好的办法就是使用返回一个promise 并且决策下一个then需要的值!

拦截流程

  1. 发起一个http请求
  2. 调用 __defaultRequest 方法
  3. __defaultRequest 遍历拦截器函数,缓存拦截器函数,具体的流程promise连接处理请求
    • Promise.resolve(?config)
    • 遍历拦截器
    • 注入拦截器
    • 发起http请求
    • 注入响应拦截器
    • 返回promise

这里面一个需求就是添加🔐,我们能够中断后面的请求,

改进

  • 我们将请求拦截器和响应拦截器,分开添加,做到和axios具有相同的开发体验
  • 我们无感授权的时候,我们要将过期的登录的请求,锁在一个队列中,等到无感授权之后,我们要将这些请求重新执行,这里有个类似于与 axios 的包 flyio

问题的解决方案

拦截器的开始是:

 //  初始化拦截器
let requestInterceptors = []
let responseInterceptors = []

// 初始化拦截器的promise
let promise = Promise.resolve(?config)

// 缓存拦截器
this.interceptors.forEach(n => {
    // n 是注册拦截器,保存在 handlers 里面
    if (n.request || n.requestError) {
        requestInterceptors.push(n.request, n.requestError)
    }
            // reponse 函数参数:response 目前还不知道是啥
    if (n.response || n.responseError) {
        responseInterceptors.unshift(n.response, n.responseError)
        }
})

// 添加请求拦截器
promise = chainInterceptors(promise, requestInterceptors)

// 发起 http 请求
promise = promise.then(serverRequest)

// 注入响应拦截器
promise = chainInterceptors(promise, responseInterceptors)

// 返回这个 promise
return promise

获取一个 promise 的值,我们可以知道,其实拦截器里面的东西就是一个链式的 promise, 处理了之后教给下一个 promise,然后把这个 promise 返回出来。

理解注入拦截器

首先注入的拦截也是要返回的 promise, 才能被链式调用。注入拦截函数的参数promise, 和 interceptors(请求拦截器),

const chainInterceptors = (promise, interceptors) => {
    for (let i = 0, ii = interceptors.length; i < ii;) {
        let thenFn = interceptors[i++]
        let rejectFn = interceptors[i++]
        // then方法调用之后,形成一个新的Promise
        // thenFn 参数是 request 此时是
        promise = promise.then(thenFn, rejectFn)
    }
    return promise
}
const transformData = (data, header, status, fns) => {
    fns.forEach(fn => {
        data = fn(data, header, status)
    })
    return data
}
const serverRequest = config => {
    const __config = Object.assign({}, config, {
        data: transformData(?config.data, ?config.header, undefined, defaults.transformRequest),
    })
    return this.__http(__config).then(transformResponse,transformResponse)
    }

请求的关于拦截器的部分

  1. 定义拦截器缓存器
  2. Promise 决策请求配置文件配置文件
  3. 遍历拦截器,将拦截器函数,放到拦截器缓存器
  4. 注入请求拦截器,注入请求拦截,就是使用 promise的then方法执行request函数,request 返回的也是 promise 的情况,这里还是一份请求的配置,请求的配置被决策到新的promise里面,在promise 里面把请求发送出去。请求的也是一个函数吗,在promise 的then的链式调用中
  5. 发起请求,底层使用 wx.request(obj) + promise 来实现功能
  6. 注入响应拦截器
  7. 返回 promise