如何在 componentWillUnmount 中中止运行 async/await xmlHttpRequest?

Posted

技术标签:

【中文标题】如何在 componentWillUnmount 中中止运行 async/await xmlHttpRequest?【英文标题】:How to abort running async/await xmlHttpRequest within componentWillUnmount? 【发布时间】:2018-05-07 20:45:53 【问题描述】:

这是代码...你将如何中止这样的 ajax 调用?

或者,如何防止 react 给我一个错误“setState called on unmounted component”?

(httpGet 只是 XMLHttpRequest 的一个包装器和一个 promise)

async componentDidMount() 
    const response = await httpGet("/ajaxRequest");
    if(response) 
        //the component has already been unmounted
        this.setState(() => (success: true));
    


componentWillUnmount() 
    //should abort possible running ajax

编辑: 这是包装:

const httpGet = function (url) 


    const request = new XMLHttpRequest;
    request.open("GET", url, true);

    return new Promise((resolve, reject) =>  
        request.onload(response => 
            resolve(response);
        );

        request.onerror(() => 
            reject("Network error");
        );

        request.send();
    );
;

【问题讨论】:

我们能知道这个包装器的外观吗? 如果您可以控制包装器,则 React 文档中描述了一种模式 reactjs.org/blog/2015/12/16/ismounted-antipattern.html @AbdennourTOUMI 我添加了包装器 伟大的@IvanHanák。我给你一个答案。享受吧! 【参考方案1】:

为了能够随时中止它,XMLHttpRequest 包装器应该:

要么用承诺返回请求对象本身。

或在包装器之外创建请求。

或使用 sub/pub 库(如 mufa 或 redux)。

我会选择第二个选项

const httpGet = function (url, request = new XMLHttpRequest())  // 2 arguments ??

    request.open("GET", url, true);

    return new Promise((resolve, reject) =>  
        request.onload(response => 
            resolve(response);
        );

        request.onerror(() => 
            reject("Network error");
        );

        request.send();
    );
;

现在在componentDidMount

async componentDidMount() 
    this.request = new XMLHttpRequest();
    const response = await httpGet("/ajaxRequest", this.request);
    if(response) 
        //the component has already been unmounted
        this.setState(() => (success: true));
    

现在在componentWillUnmount:

componentWillUnmount() 
  if (this.request && this.request.abort) 
    this.request.abort();
  

就这么简单。 如果您不想中止,那么您的第一个包装器 (httpGet) 仍然有效,因为第二个参数 (request) 是可选的。

【讨论】:

完全正确 - 我想过类似的事情

以上是关于如何在 componentWillUnmount 中中止运行 async/await xmlHttpRequest?的主要内容,如果未能解决你的问题,请参考以下文章

我们如何使用 componentWillUnmount() 方法从 DOM 中删除组件 React? [关闭]

取消 componentWillUnmount 方法中的所有 Subscriptions 和 Asyncs,如何?

clearInterval 在 componentWillUnmount 中不起作用

商店的变更监听器没有在 componentWillUnmount 上被删除?

useEffect 模拟 componentWillUnmount 不返回更新状态

来自 componentWillUnmount() 的调度操作