Axios用cancelToken取消未完成的异步请求

By
写代码

有些问题,可能由于网速提升太快,慢慢被我们淡忘,比如雪碧图、连接合并这些优化。但是另外还有些容易忽略的问题,比如对于发起的ajax请求,有时需要手动终止,尤其是react的组件,有时在unmounted组件上没清理异步调用,就会碰到警告。

开发时把网络速度调整到slow 3G,发现部分组件报了警告:

Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

造成这个问题对原因是,在已经unmounted的组件上,有异步回调函数触发,然后函数内部还有state的更新操作。解决问题也给的很清楚:在useEffect的清理函数(返回的函数)里,取消异步任务的订阅。

那么,对于使用Axios库的项目,如果是已经发起的ajax请求,如何手动终止呢?顺着文档,找到了cancelToken这个选项。

相关代码块

对于浏览器(区别于node),Axios创建的异步连接,本质上是新建了一个XMLHttpRequest,然后包装Promise。

cancelToken.source是个工厂函数,通过它,返回token实例和一个cancel处理函数。

可以看到,整体思路是在xhrAdapter里新建了一个XHR连接,然后通过config.cancelToken.promise.then的处理,来达到终止XHR连接(abort)的目的。

作为一个Promise,要触发then,这个Promise必须resolve,而这个resolve,则应该是可以由用户触发的,才能达到目的。

CancelToken这个构造函数,返回的实例,包含一个promise。

source()函数里,new CancelToken的时候,executor函数只有一个操作:cancel = c。

这里executor(function cancel(...) {...})),实际把整个函数赋值过去,即cancel = function cancel(...) {...})。然后把这个cancel函数,连同CancelToken实例,一起暴露给用户。即,必须在CancelToken实例上执行对应的cancel函数,才会起效。

总结

所以梳理一下执行流程就是:

cancel-axios-req
CancelToken流程

由于每个axios.get/post都会生成一个对应的XHR连接,所以,每个连接都需要由source()工厂函数,生成新的token和对应的cancel,否则,使用相同的token,调用cancel时,会把几个连接一起停掉,这一点需要注意。

0

Comments: 0

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

:razz: