无感刷新Token时的小知识点:闭包保持信息不丢失

闭包概念:

闭包是JavaScript中的一个重要概念,它允许一个函数访问并操作函数外部的变量。闭包发生在一个函数内部创建另一个函数时,内部函数会记住并访问其被创建时的环境。

闭包的特点

  1. 访问外部变量:闭包可以访问定义它的函数中的变量,以及全局变量。
  2. 记忆环境:即使外部函数已经执行完毕,闭包仍然可以记忆并访问外部函数的变量。这是因为闭包保留了包含它的函数的作用域链。
  3. 封装性:闭包提供了一种封装私有变量的方式,使得这些变量不会被全局作用域直接访问,从而避免全局命名冲突。

闭包的优点

  1. 数据封装:闭包可以用来模仿私有属性和方法,提供对象封装的能力。
  2. 保持状态:闭包可以在函数外部保持和操作内部变量的状态,适合用于实现回调、事件处理器和任何需要状态保持的场合。
  3. 模块化代码:可以利用闭包来创建模块化和可重用的代码块,提高代码的组织性和可维护性。

闭包的缺点

  1. 内存消耗:闭包可能会导致比不使用闭包时更高的内存消耗,因为闭包的作用域链中的变量不会在外部函数执行完毕后立即被垃圾回收,只有当闭包本身被销毁后,这些变量的内存才会被释放。
  2. 性能考虑:在一些性能敏感的应用中,过度使用闭包可能会导致内存占用过高或性能下降。
  3. 理解难度:对于初学者来说,闭包的概念可能比较难以理解,尤其是闭包的作用域和生命周期。

尽管闭包带来了一些性能和内存的考虑,但它们在JavaScript编程中提供了极大的灵活性和功能。合理使用闭包可以极大地提升代码的表达力和封装性。

无感刷新token示例:

            // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
            if (!isRefreshToken) {
                  //刷新令牌操作
            } else {
                // 添加到队列,等待刷新获取到新的令牌
                return new Promise(resolve => {
                    requestList.push(() => {
                        res.config.headers['Authorization'] = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 
                        resolve(axiosInstance(res.config))
                    })
                })
            }

requestList.push(() => {...})这里使用匿名函数(也称为箭头函数)而不是直接将需要执行的代码或一个已定义的函数推入requestList数组的原因涉及到JavaScript中的闭包和异步执行的特性。以下是几个关键点来解释为什么在这种场景下使用匿名函数是必要的:

  1. 延迟执行:将函数推入数组而不是直接执行的代码或结果,意味着你希望将这个函数的执行延迟到未来的某个时间点。在这个例子中,当新的令牌被获取之后,数组中的每个函数将被依次取出并执行,这样做可以确保使用最新的令牌来重新发送HTTP请求。

  2. 闭包:匿名函数创建了一个闭包,这意味着它可以捕获并保持对其创建时作用域中变量的引用。在这个例子中,匿名函数内部引用了resgetAccessToken等外部变量。通过这种方式,每个函数都能够访问到在其被推入数组时的具体res对象以及在执行时能够调用getAccessToken来获取当前的令牌。如果直接推入一段代码或一个非闭包函数,那么这些细节的上下文可能会丢失。

关于数组队列中的执行过程

res.config.headers['Authorization'] = 'Bearer ' + getAccessToken()这句代码会先执行,然后才会执行resolve(axiosInstance(res.config))

这里的执行流程如下:

  1. 当这个匿名函数(推入requestList数组中的函数)被调用时,它首先会执行res.config.headers['Authorization'] = 'Bearer ' + getAccessToken()这一行代码。这一步的作用是更新请求配置(res.config)的Authorization头部,将其设置为最新获取的访问令牌(Token)。

  2. 更新了请求头部之后,紧接着执行的是resolve(axiosInstance(res.config))。这一步调用axiosInstance,传入更新后的请求配置res.config作为参数,从而重新发送HTTP请求。resolve函数的调用标志着返回的Promise对象将被解决(即成功状态),并且其解决值是axiosInstance(res.config)的返回结果,这通常是另一个Promise对象,表示HTTP请求的异步操作。

这种设计确保了在重新发起请求之前,请求的Authorization头部已经被更新为最新的令牌值,这是处理认证令牌更新逻辑中的一个典型步骤。通过这种方式,可以确保每次重试请求时都使用最新的认证信息,避免因为令牌过期而导致请求失败。

发表评论 / Comment

用心评论~