【问题标题】:Cancel previous promise取消之前的承诺
【发布时间】:2019-01-30 20:16:00
【问题描述】:

我正在我的 React 应用程序中实现搜索输入,根据结果集的大小,这可能需要几秒钟的时间才能得到来自服务器的响应。我现在遇到的问题是,如果用户搜索具有较大结果集的术语,然后立即搜索具有较小结果集的术语,则第一次搜索在最后一次搜索后返回并覆盖数据,因此在表格上显示不正确的结果。

目前我有一个搜索组件,它在其父组件中调用一个异步函数(该函数可以从多个子组件调用,搜索就是其中之一)。在异步函数内部,我使用搜索查询对服务进行了等待调用。一旦返回结果将被传递给更新某些状态的函数。

我已阅读有关取消令牌的信息,但我不完全确定如何实现这一点。当搜索组件进行初始调用时,将有一个待处理的承诺,直到收到结果。当我再次搜索时,我怎么能忽略第一个承诺的结果?每次我搜索时,我会将承诺存储在组件的一个字段中,并在以后的搜索中以某种方式检查该字段吗?

我在网上阅读了许多可能的解决方案。我正在使用fetch-retry 来处理API 调用,并且宁愿不使用诸如bluebirdaxios 之类的库。我不明白的主要部分是如果将来创建了一个承诺,如何让我的承诺无法解决。

希望我解释得足够清楚!

谢谢

【问题讨论】:

标签: javascript reactjs promise cancellation


【解决方案1】:

当我再次搜索时,我怎么能忽略第一个承诺的结果?

您可能不希望这样,因为如果您提出请求并忽略其结果,您将浪费一些带宽。相反,您应该取消基础请求(不是承诺,承诺不能直接取消)。

为此,您可以为每次搜索保留一个中止控制器:

 this.controller = new AbortController();

然后启动所有获取请求:

 fetch(url, { signal: this.controller.signal })
   .then(res => res.json())
   .then(res => this.setState({ /*...*/ }))
   .catch(() => /*..*/)

现在,如果您重新开始搜索,请执行以下操作:

 this.controller.abort();
 this.controller = new AbortController();

然后再次提取。

Read on

【讨论】:

  • 这里是浏览器兼容性图表:caniuse.com/#search=abort
  • 谢谢,我也读到了 AbortController,但我认为它不能在 IE11 上使用,而且我所在的受限环境没有可安装的 polyfill。如果我要使用 AbortController,我是否会在我的主要组件状态中只拥有一个实例。当调用搜索函数时,我将该控制器传递给 api 函数调用并将其附加到 fetch。然后我在搜索功能开始时调用this.controller.abort()
  • @sam 不,您应该将它绑定到管理它的组件(Search ?)
猜你喜欢
  • 1970-01-01
  • 2015-01-23
  • 2017-10-09
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 2015-06-24
相关资源
最近更新 更多