zoukankan      html  css  js  c++  java
  • 多个请求间断失败,如何优雅处理?

    背景

    试想这样一个场景:在访问系统的某个页面时,会发出多个请求,恰巧在某个时间点,登录信息过期了,这个时候需要自动跳转到登录页。由于请求返回的时间不一致,可能会多次执行跳转,造成使用困扰。

    问题核心

    法律常识告诉我,不能对同一行为进行多次评价。所以,我们也不能对同一错误进行多次处理。

    解决方案:发布订阅

    每次请求,可以订阅一次事件(譬如叫 logoutHandler),当一个请求出错则广播错误信息,那些订阅了这个事件的请求,就不再处理后续的响应了。伪代码如下:

    const PubSub = {}
    
    const request = opt => {
      let isErrorHandled = false
      PubSub.subscribe('logoutHandler', () => isErrorHandled = true)
    
      return fetch(opt)
        .catch(e => {
          if (isErrorHandled) throw null
    
          if (e.status === 'logout') {
            PubSub.publish('logoutHandler', e)
            // redirect to login page
          }
          throw null
        })
    }
    

    很好,解决了上面的问题。但,这样做会导致内存随请求的增加而线性增长。有没有更好的方案?

    解决方案:时间治愈一切

    在初始化过程中,设置一个起始时间戳。每次请求,再对该请求附加一个当前时间戳。当发现用户信息失效,则重置起始时间戳。根据时间的大小,决定是否处理错误信息。伪代码如下:

    let __startTime = Date.now()
    
    const request = opt => {
      const requestTime = Date.now()
    
      return fetch(opt)
        .catch(e => {
          const isErrorHandled = requestTime <= __startTime
          if (isErrorHandled) throw null
    
          if (e.status === 'logout') {
            __startTime = Date.now()
            // redirect to login page
          }
    
          throw null
        })
    }
    

    这种方式,无论是时间开销还是内存开销,都可以忽略不计。

    进一步优化

    当应用已经跳转到登录页了,即使之前的请求响应正常,其实也不需要再处理了。

    let __startTime = Date.now()
    
    const request = opt => {
      const requestTime = Date.now()
    
      return fetch(opt)
        .then(res => { // 新增:不再处理正常响应
          const isErrorHandled = requestTime <= __startTime
          if (isErrorHandled) throw null
    
          return res
        })
        .catch(e => {
          const isErrorHandled = requestTime <= __startTime
          if (isErrorHandled) throw null
    
          if (e.status === 'logout') {
            __startTime = Date.now()
            // redirect to login page
          }
    
          throw null
        })
    }
    
  • 相关阅读:
    数据分析普遍存在的方法及理论有哪些?-数据分析师
    R语言 我要如何开始R语言_数据分析师
    R语言 我要如何开始R语言_数据分析师
    Root(hdu5777+扩展欧几里得+原根)
    CF#256(Div.2) A. Rewards
    HDU-4031-Attack(树状数组)
    POJ 3253 Fence Repair(哈夫曼树)
    Python的Django框架中的Context使用
    C++中面向对象的理解
    统计输入的单词中有几个长度大于n的,n是自己指定的,用函数对象实现
  • 原文地址:https://www.cnblogs.com/fayin/p/14690911.html
Copyright © 2011-2022 走看看