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

32

我了解使用AbortController.abort()来取消fetch请求的方法。在执行此命令后,是否有一种方式可以重新开始请求而不必取消它?

例如,在MDN上的这个演示中,一旦点击“取消下载”,再次点击“下载视频”将会触发fetch请求,但会立即被取消。

是否有一种方法可以允许重新启动此请求而不必取消它呢? 因此,例如在这种情况下,您如何单击“下载视频”开始下载,单击“取消下载”取消下载,然后再次单击“下载视频”重新开始下载呢?例如,如果用户误点击“取消下载”...

3个回答

28

无法做到。

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

我认为这是出于设计考虑。否则可能会变得混乱,例如,如果您将控制器或信号交给某个外部库,突然他们可以远程取消中断您的内部状态。


它是幂等的。通常是异步设计的核心部分。 - Hunter Kohler

8
例如,在MDN的这个演示中,一旦点击了“取消下载”,再次点击“下载视频”将会再次触发fetch,但是立即中止它。
他们修复了example。在你点击“取消下载”后,你可以一遍又一遍地开始新的下载并再次取消。为了实现这一点,“下载按钮”每次实例化一个新的AbortController,这样你就可以每次得到一个新的信号来中止操作。
downloadBtn.addEventListener('click', fetchVideo);

function fetchVideo() {
  controller = new AbortController();
  signal = controller.signal;
  // ...

所以,为每个可能需要取消的请求实例化新的AbortControllers是可以的。

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();
        }
    }

    ...

}

也许这不是最优雅的解决方案,但它能够正常工作。

祝好!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接