问题是,如果客户端在中间取消了下载,则不会调用Finally方法,似乎promise 会永远留在内存中,永远不会得到解决.
如果浏览器下载真的被取消,我无法在Chrome或Edge和NodeJS版本16.14.2中重现这个问题.当我开始一个巨大的下载,并通过点击Chrome下载栏中的"取消"选项来取消下载时,我立即得到了一系列事件,并看到管道promise 拒绝并拨打.finally()
.
我想知道你是不是真的要在浏览器中取消下载.在Chrome和Edge(我没有try 过其他浏览器)中,仅仅关闭下载的标签或窗口并不会停止下载.您必须物理取消下载,或者退出整个浏览器,并在出现停止下载的提示时回答"是".
以下是我在Chrome和Edge中手动取消下载时收到的事件:
- 关闭
res
流上的事件
- 下载程序上的错误事件:ERR_STREAM_PROFILE_CLOSE
- 下载程序流上的关闭事件
.catch()
%的管道promise :ERR_STREAM_PROFILE_CLOSE
.finally()
%的流水线promise
- 下载程序流上的错误事件:ECONNRESET
在Edge浏览器中,如果我完全退出浏览器,并在提示取消"正在进行"下载时回答"是",那么我会得到:
- 关闭
res
流上的事件
- 下载程序上的错误事件:ERR_STREAM_PROFILE_CLOSE
- 下载程序流上的关闭事件
.catch()
%的流水线promise
.finally()
%的流水线promise
- 下载程序流上的错误事件:ECONNRESET
仅供参考,我使用这个URL进行大型下载:"http://speedtest-sgp1.digitalocean.com/5gb.test"From This Site:https://testfiledownload.com/作为大型下载的来源.
以下是我的测试代码:
const express = require('express');
const stream = require('stream');
const { pipeline } = require('node:stream/promises');
const got = require('got');
const app = express();
const url = "http://speedtest-sgp1.digitalocean.com/5gb.test";
let currentDownloadsStream = 0;
app.get('/download', async (req, res) => {
currentDownloadsStream++;
const downloader = got.stream(url);
downloader.on('end', () => {
console.log("end event on downloader");
}).on('close', () => {
console.log("close event on downloader");
}).on('error', err => {
console.log("error event on downloader");
console.log(err);
});
res.on('finish', () => {
console.log("finish event");
}).on('end', () => {
console.log("end event on res");
}).on('prefinish', () => {
console.log("prefinish eventon res");
}).on('close', () => {
console.log("close event on res");
}).on('error', err => {
console.log("error event on res");
console.log(err);
});
pipeline(downloader, res).then(result => {
console.log(".then() called");
}).catch(err => {
console.log(".catch() called");
console.log(err);
}).finally(() => {
console.log(".finally() called");
currentDownloadsStream--;
})
});
app.listen(80);