如何在 AbortController.abort() 之后启动另一个请求?

jen*_*son 5 asynchronous httprequest abort fetch

我已经阅读了有关使用AbortController.abort()取消获取请求的信息。有没有办法在调用此命令后再次启动请求而不中止它?

例如,在MDN 的这个演示中,一旦点击取消下载,点击下载视频将再次触发获取,但立即中止。

有没有办法在不中止它的情况下再次允许这个请求?那么,在这种情况下,如何单击“下载视频”开始下载,单击“取消下载”取消下载,然后再次单击“下载视频”再次开始下载?例如,如果用户不小心点击了取消下载...

flo*_*ori 28

你不能。

一个AbortController或其信号不能被重用或重置。如果您需要“重置”它,则必须创建一个新AbortController实例并使用它。

我认为这是设计使然。否则,它可能会变得混乱,例如,如果您将控制器或信号移交给某些外部库,并且突然他们可以远程取消您的内部状态。


Raf*_*eco 8

例如,在 MDN 的这个演示中,一旦单击“取消下载”,单击“下载视频”将再次触发获取,但会立即中止它。

他们修正了这个例子。单击后,Cancel download您将能够开始新的下载并再次取消下载,一遍又一遍。为了实现每次都Download button实例化一个新的AbortController,这样你每次都会收到一个新的中止信号:

downloadBtn.addEventListener('click', fetchVideo);

function fetchVideo() {
  controller = new AbortController();
  signal = controller.signal;
  // ...
Run Code Online (Sandbox Code Playgroud)

因此,可以为您希望取消的每个请求实例化新的 AbortController。


小智 3

我知道这可能有点晚了,但无论如何我都会留下这个答案,以防有人需要。

我不知道这是否是最佳方法,但为了继续执行获取请求(使用“相同”信号),我必须AbortController为每个请求创建一个新实例。

就我而言(所有代码都包含在类声明中),我每次都删除并创建一个新实例,如下所示:

class Foo Extends Bar {

    abort_controller_instance = false;

    constructor(params){
        super(params);
        this.resetOrStartAbortController();
    }

    resetOrStartAbortController(){
        if(this.abort_controller_instance){
            delete this.abort_controller_instance;
        }
        this.abort_controller_instance = new AbortController();
    }

    abortFetchRequest(){
        if(this.abort_controller_instance){
            this.abort_controller_instance.abort();
            this.resetOrStartAbortController();
        }
    }

    ...

}
Run Code Online (Sandbox Code Playgroud)

也许这不是最优雅的解决方案,但它确实有效。

问候!