为什么在 React 中,cancelledPromise 模式被认为比 isMounted() “反模式”更好?

IT技术 javascript reactjs
2021-05-15 07:29:33

参见这里:https : //reactjs.org/blog/2015/12/16/ismounted-antipattern.html 还有这里:How to cancel a fetch on componentWillUnmount这里:ismounted antipattern, track own property

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

  • 在您的promise.resolve检查中this.IsMounted(),如果`Compounted Has Unmounted,哪个React将为您正确返回
  • 在您的promise.resolve支票中_isMounted,您已在ComponentWillUnmount()方法中手动跟踪
  • 使用可取消的Promise,这样你promise就永远不会解决。这将解决您的所有问题并使其变得可爱。

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

因此,实际上,第三个选项归结为: - 在您的promise.errorcheck 中errorPayload.IsCancelled,您已在cancellablePromise对象中手动跟踪该对象,而对象又由ComponentWillUnmount.

所以这三个几乎完全相同:

当您处理promise结果时,请检查该变量的值,该变量与组件是否已经有unmounted.

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

3个回答

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

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

尽管差异可能是语义上的,但语义本身对可维护性具有value。在这种情况下,可取消的Promise用于在结构上并置关注点,将可能是一般问题的行为附加到正常的特定情况。

isMounted不推荐使用组件方法。它不能再在 React 16 中使用了。

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

对于可取消的Promise,这不是问题。更重要的是,这种模式允许实际取消异步过程,例如,Axios 在取消期间实际上取消了 XHR 请求。尽管如此,为了使这项工作发挥作用,这需要整个Promise链都具有取消意识。这可能很乏味,因为本机Promise不支持取消,包括async..await.

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

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

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