如何避免让不再有用的异步重击(应用程序不再期待它)能够更新状态?
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
的情况添加一个异常,而不做任何事情。
扩展一下您的具体情况:一个好的经验法则是,如果您在卸载组件时发现自己正在“重置”状态,那么它首先应该只是本地组件状态。
【讨论】:
以上是关于如何避免让不再有用的异步重击(应用程序不再期待它)能够更新状态?的主要内容,如果未能解决你的问题,请参考以下文章