为什么 cancel Promise 模式被认为比 React 中的 isMounted() "antipattern"更好?



请参阅此处: https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html 还有这里: 如何取消组件上的获取将卸载 在这里:安装反图案,跟踪自己的财产

在这两种情况下,他们都提到了 3 种方法:

  • 在您的promise.resolve检查this.IsMounted(),如果"已卸载",则 React 将为您正确返回
  • promise.resolve检查_isMounted中,您已ComponentWillUnmount()方法手动跟踪。
  • 使用可取消的承诺,这样你promise就永远不会解决。这将解决您的所有问题并使其变得可爱。

除了在第三种情况下,您的promiseerror(),但在其他情况下也可能error()(例如 API 已关闭)。

所以实际上第三个选项归结为: - 在您的promise.error检查errorPayload.IsCancelled中,您在cancellablePromise对象中手动跟踪了该对象,而该对象又由ComponentWillUnmount中的手动调用触发。

所以这三者几乎相同:

处理promise结果时,请检查此变量的值与组件是否已unmounted直接相关。

为什么他们断言第三个选项比其他两个选项更好,并且第一个选项是反模式。

这里的关键要素是if (this.isMounted()) { setState(...) }通常是一种反模式。它可能导致压制有用的警告,因此应该怀疑它的出现,因为在大多数情况下,它代表了掩盖实际问题的机会。因此,即使其行为在功能上与其他一些方法相同,另一种方法也是可取的。

在 API 调用的情况下,您可能希望忽略承诺的结果是完全合理的,因为它不再相关。使用取消的承诺在语法和语义上将是否专门忽略结果的逻辑与 API 调用相关联,这可以防止将来的开发人员意外在另一个上下文中使用该代码并可能抑制有意义的警告。

尽管差异可能是语义上的,但语义本身对可维护性具有价值。在这种情况下,可取消的承诺用于在结构上共同定位关注点,将通常可能成为问题的行为附加到可以接受的特定情况下。

isMounted组件方法已被弃用。它不能再在 React 16 中使用。

没有内置的_isMounted状态,它应该由用户在组件生命周期钩子中定义。在某种程度上,这是一个偏好问题。它的问题在于它需要承诺链耦合到组件实例才能访问this._isMounted

对于可取消的承诺来说,这不是问题。更重要的是,这种模式允许实际取消异步进程,例如 Axios 实际上在取消期间取消 XHR 请求。尽管如此,为了做到这一点,这需要整个承诺链具有取消意识。这可能很乏味,因为本机承诺(包括async..await)不支持取消。

可观察量提供了更强大的方法来控制执行。有一个单点(订阅)能够通过调用取消订阅函数来取消整个链:

const unsubscribe = fetchData()
.mergeMap(asynchronousProcessing)
.mergeMap(yetAnotherAsynchronousProcessing)
.subscribe(data => this.setState(data));

让我们想象一下,将导致将来setState调用执行大量计算或执行大量网络请求的操作。所有这些资源都将被使用,然后在将来某个时候,当承诺解决时,它意识到不需要所有的工作,因为用户已经离开了页面的那部分,并且所有的工作都将被丢弃。这对性能和网络/内存使用不利,特别是如果你有很多元素出现和消失。如果使用选项 3,则只会浪费少量资源,直到到达下一个停止点并释放资源。我假设他们删除了 1) 强制代码编写者使用 3),并提出了 2) 用于不可能/难以迁移的情况。

最新更新