惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
量子位
小众软件
小众软件
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
V
Vulnerabilities – Threatpost
Know Your Adversary
Know Your Adversary
T
Threat Research - Cisco Blogs
Latest news
Latest news
Spread Privacy
Spread Privacy
C
Cyber Attacks, Cyber Crime and Cyber Security
NISL@THU
NISL@THU
T
Tor Project blog
Hacker News: Ask HN
Hacker News: Ask HN
V2EX - 技术
V2EX - 技术
T
The Exploit Database - CXSecurity.com
博客园 - 三生石上(FineUI控件)
K
Kaspersky official blog
Cyberwarzone
Cyberwarzone
博客园 - 叶小钗
博客园 - 聂微东
Last Week in AI
Last Week in AI
爱范儿
爱范儿
腾讯CDC
博客园 - Franky
美团技术团队
J
Java Code Geeks
O
OpenAI News
L
Lohrmann on Cybersecurity
Simon Willison's Weblog
Simon Willison's Weblog
有赞技术团队
有赞技术团队
T
Threatpost
G
GRAHAM CLULEY
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
宝玉的分享
宝玉的分享
I
Intezer
N
News and Events Feed by Topic
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
S
Security @ Cisco Blogs
Forbes - Security
Forbes - Security
N
News | PayPal Newsroom
Stack Overflow Blog
Stack Overflow Blog
Scott Helme
Scott Helme
H
Hacker News: Front Page
Cloudbric
Cloudbric

博客园 - Liaofy

前端新范式:用 AI 提效开发,用 E2E 保证迭代质量 把SPA的加载速度提升一倍,有没有搞头? 使用mumu模拟器抓包 andriod app 如何在本地给 vue-router4 扩展功能? Vue3 路由优化,使页面初次渲染效率翻倍 【eslint 插件开发】禁用 location 跳转外部链接 vue 项目使用 charles 代理线上页面到本地后显示404 避免使用单个数字作为对象的key 高扩展弹出层组件设计实现(H5&小程序) 轻松搞懂POST与PUT的区别 vite(or rollup) 实现 webpackChunkName webapp项目架构畅想(vue3).md vite试玩:老项目启动从6分钟到秒开 修剪AST树减少webapck打包尺寸 【uniapp】改善中大型uniapp小程序项目开发体验 vscode 调试 webpack 打包 5分钟,搞清 Unicode 与 UTF-8 的区别 deAsync.js 真正让异步变同步 盘的转——使用缓动函数完成动画
多个请求间断失败,如何优雅处理?
Liaofy · 2021-04-22 · via 博客园 - Liaofy

背景

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

问题核心

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

解决方案:发布订阅

每次请求,可以订阅一次事件(譬如叫 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
    })
}