用户事件上的流保护程序取消/中止下载

Aye*_*era 6 javascript download fetch large-files

我正在使用Streamsaver.js下载更大的文件,它工作得很好。

与此同时,我想处理用户的取消事件以停止从服务器获取内容。

是否可以使用 AbortController 和 AbortSignal 来停止可读流获取数据?

下载部分的示例代码如下。

fetch(url, { signal: abortSignal })
    .then(resp => {
        for (var pair of resp.headers.entries()) {
            console.log(pair[0] + ': ' + pair[1]);
        }
        total = Number(resp.headers.get('X-zowe-filesize'));
        return resp.body;
    })
    .then(res => {

        var progress = new TransformStream({
            transform(chunk, controller) {
                loaded += chunk.length;
                controller.enqueue(chunk);
                elem.style.width = (loaded / total) * 100 + '%';
                elem.innerHTML = (loaded / total) * 100 + '%';
            }
        })

        const readableStream = res
        // more optimized
        if (window.WritableStream && readableStream.pipeTo) {
            return readableStream
                .pipeThrough(progress)
                .pipeTo(fileStream, { signal: abortSignal })
                .then(() => console.log('done writing'))
        }

        window.writer = fileStream.getWriter()

        const reader = readableStream.getReader()
        const pump = () => reader.read()
            .then(res => res.done
                ? writer.close()
                : writer.write(res.value).then(pump))

        pump()
    })
Run Code Online (Sandbox Code Playgroud)

Joe*_*Joe 1

FWIK,可以使用AbortControllerAbortSignal停止它。AbortController允许您创建一个AbortSignal可以作为信号选项传递给 fetch API 的信号选项。一旦 fetch API 收到此信号,它将停止从服务器获取数据。

您可以像这样将 传递abortSignal给 fetch API:fetch(url, { signal: abortSignal })。在您在帖子中提供的代码中,似乎您已正确配置此设置。您可能还需要将 传递abortSignal给该pipeTo方法,以便在用户取消下载时可以使用它来停止将文件写入流。

您可以将 传递abortSignalpipeTo这样的方法:pipeTo(stream, { signal: abortSignal })

为此,您可以创建一个函数来调用 AbortController 的abort()方法来取消读取和写入。以下是如何执行此操作的基本实现:

const controller = new AbortController(); // Create a new AbortController
const abortSignal = controller.signal; // And make the signal easier to access

// Do a simple fetch and pass the signal to it
// If we don't call AbortController.abort() it will continue
fetch(url, { signal: abortSignal }).then((res) => {
   // Write to a stream
   if (window.WritableStream && readableStream.pipeTo) {
      return readableStream
         .pipeThrough(progress)
         .pipeTo(fileStream, { signal: abortSignal })
         .then(() => console.log("done writing"));
   }
});

function cancel() {
   // Call the `abort()` method and stop the fetch
   controller.abort();
}
Run Code Online (Sandbox Code Playgroud)

在此代码中,当用户调用 时cancel()abort()会在 AbortController 上调用该方法,然后 AbortController 会在完成写入文件之前无意中停止fetch()和。readableSteam