为啥在 componentDidMount 中取消异步/ajax 请求

Posted

技术标签:

【中文标题】为啥在 componentDidMount 中取消异步/ajax 请求【英文标题】:Why does an asynchronous/ajax request get cancelled in componentDidMount为什么在 componentDidMount 中取消异步/ajax 请求 【发布时间】:2018-12-19 00:24:52 【问题描述】:

如果我的componentDidMount 生命周期中有一个 api

constructor() 
   this.source = axios.CancelToken.source();


componentDidMount() 
  axios.get('some-api-url', 
    cancelToken: this.source.token,
  );
  .then(res => 
     // set state here or do something based on response i get
  )
  .catch(error => 
    // handle error
  )


componentWillUnmount() 
  this.source.cancel('request cancelled');

回到我的问题,为什么我必须这样做,只是为了避免这个错误;

警告:无法在未安装的组件上调用 setState(或 forceUpdate)。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请在 componentWillUnmount 方法中取消所有订阅和异步任务。

如果我只是加载这个组件而我什至没有以任何方式卸载该组件,为什么它仍然被卸载。

我正在使用 react 路由器,每次使用我切换页面时都会收到 setState 错误。为什么我会收到此错误?为什么必须取消componentDidUnmount中的ajax调用的所有订阅?

【问题讨论】:

能否包含您的 React Router 代码以显示您如何使用此组件? 【参考方案1】:

我是新来的反应,无论如何我会回答这个问题。这就是我认为正在发生的事情

您必须考虑两件事。第一个是 React,第二个是你在 componentDidMount 中发送的异步请求。

一旦当前组件被挂载,componentDidMount 就会被触发并发送异步请求。由于您使用的是axios,它将返回一个承诺。现在承诺正在等待解决(或拒绝),一旦发生,您将更新状态。

现在,当您切换到新页面时,当前组件将被卸载。但请注意,promise 尚未解决,一旦解决,将调用 then 回调并更新组件的状态(已卸载)。这就是您收到错误的原因。 如果您在卸载时取消请求,则状态不会更新(因为我们不等待承诺解决)

【讨论】:

以上是关于为啥在 componentDidMount 中取消异步/ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章

为啥必须在 componentDidMount() 期间解析函数中的函数调用?

为啥 componentDidMount 在 react.js 和 redux 中被多次调用?

为啥我不能在“foreach”循环中取消设置变量?

react的生命周期

为啥有两种方法可以在 Git 中取消暂存文件?

为啥有两种方法可以在 Git 中取消暂存文件?