如何避免让不再有用​​的异步重击(应用程序不再期待它)能够更新状态?

Posted

技术标签:

【中文标题】如何避免让不再有用​​的异步重击(应用程序不再期待它)能够更新状态?【英文标题】:How to avoid letting an async thunk that is no longer useful (the app is not expecting it anymore) from being able to update the state? 【发布时间】:2021-06-28 05:04:17 【问题描述】:

我的单页应用程序(React + Redux)有以下模式。

每次在应用程序上加载页面时它都会运行。用户导航到特定页面,并调度 loadPageThunk。页面的初始状态向用户显示了一个微调器。例如,在博客文章页面中使用。

该 thunk 将获取一些异步数据(博文),然后将显示包含该数据的页面。

它工作正常。当用户离开页面时。 useEffect 调度 RESET 操作以将状态重置为其初始值。

我的问题是:

如果异步调用需要很长时间才能完成并且用户导航离开怎么办?这将产生一个问题,因为现在有一个未决的承诺将在意想不到的时间完成。如何防止该完成更新我的状态?

想象一个需要 10 秒才能完成的异步调用的以下步骤:

#### FIRST PAGE LOAD ####

USER VISITS blog/slug-1
loadPageThunk() IS DISPATCHED
blogPost1 STARTS GETTING FETCHED (WILL TAKE 10 SECONDS)
USER NAVIGATES AWAY

#### SECOND PAGE LOAD ####

USER VISITS blog/slug-2
blogPost2 STARTS GETTING FETCHED (WILL TAKE 10 SECONDS)
USER IS STILL SEEING SPINNER
blogPost1 (FROM THE PREVIOUS VISIT) HAS COMPLETE AND WILL UPDATE THE STATE
USER NOW SEES blog/slug-2 WITH THE DATA FROM blogPost1 WHICH IS AN ERROR
blogPost2 WILL EVENTUALLY COMPLETE AND USER WILL SEE A CONTENT FLICKER ON THE PAGE

问题

如何避免更新状态而不再有用的未决承诺?

我的应用目前没有出现这个问题,但我认为一个好的设计应该解决这个问题。

我是否应该为我的LOAD_PAGE 循环添加一个ID,以便在允许callbacks / async code 在 ID 不匹配时更新状态之前检查当前循环的 ID?人们通常如何处理这个问题?

【问题讨论】:

【参考方案1】:

我个人将博客数据存储为entities(帖子、cmets 等),由 id 和 collections 键入。该集合只是特定页面上的帖子 ID 数组。

例如,


  entities: 
     posts: 
       1: ...,
       2: ...
     ,
     comments: 
        123: ...,
        999: ...
     
  ,
  collections: 
     "blog/slug-1": [99,98,97...],
     "blog/slug-2": [89,88,87...],
  

这种结构意味着每个页面都可以将其数据保存在正确的位置,而不管它是否是当前页面。这也意味着每个页面都可以选择自己的数据,并且可以查看该数据是否已经存在于状态中。

【讨论】:

不是个人,这被认为是很多人的好习惯:normalizing data【参考方案2】:

createAsyncThunk 返回的承诺附加了一个abort() 方法,可用于“取消”承诺。见canceling while running。您可以在清理中调用 abort() 以防止 thunk 成为 fulfilled

在你的 reducer 中,如果你正在为你的 thunk 处理 rejected 情况,那么你可以为错误名称为 AbortError 的情况添加一个异常,而不做任何事情。

扩展一下您的具体情况:一个好的经验法则是,如果您在卸载组件时发现自己正在“重置”状态,那么它首先应该只是本地组件状态。

【讨论】:

以上是关于如何避免让不再有用​​的异步重击(应用程序不再期待它)能够更新状态?的主要内容,如果未能解决你的问题,请参考以下文章

重击期待并再次回来

Mac不再丝滑?这些有用的方法了解一下

什么是美元?在重击中? [复制]

CLR 在调用 c++ 函数时如何避免重击?

6条shell小技巧,让脚本显得不再业余(1分钟系列)

有了这个日期工具类,让日期转化不再烦恼