Nodejs 中的异步方法超时
Async Method Timeout in Nodejs
我正在下载一个文件,有时文件很大,超时时间不够。超时时,我想取消下载过程,因为即使出现超时错误,它也会继续处理文件并给出以下异常
_http_outgoing.js:470
throw new ERR_HTTP_HEADERS_SENT('set'); ^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
这是我的异步方法
router.get('/api/files/GetFile', urlencodedParser, (req, res) => {
return new Promise(function (resolve, reject) {
(async function () {
try {
var folderName = "File_" + moment().format('DD-MM-YYYY HH_mm_ss');
await routerFile.CreatePdfZip(req.query.VoucherCodes, req.query.AppNames, folderName);
var fullzipPath = './FilesToDownload/' + folderName + '.zip';
zipFolder('./FilesToDownload/' + folderName, './FilesToDownload/' + folderName + '.zip', function (err) {
if (err) {
return reject(err);
} else {
console.log('zip created');
rimraf('./FilesToDownload/' + folderName, function () {
console.log("folder has been deleted");
});
fs.readFile(fullzipPath, (err2, zipData) => {
if (err2) reject(err2);
const base64 = zipData.toString('base64');
res.setHeader('Content-type', 'application/zip');
res.type('zip');
res.end(base64, 'binary');
console.log('EXCELLENT');
});
}
});
} catch (error) {
return reject(error);
}
})();
}).catch(error => {
console.log(error);
res.send(error);
});
});
错误发生在res.setHeader('Content-type','application/zip');
行
PS: 路由器变量来自 const router = express.Router();
这里是超时设置
const app = express();
app.use(timeout('2s'));
app.use(bodyParser());
app.use(haltOnTimedout);
app.use(cookieParser());
app.use(haltOnTimedout);
function haltOnTimedout(req, res, next) {
if (!req.timedout)
next();
else {
console.log('TIMEOUT.----------------------------------------------');
}
}
我在这里做错了什么?或者有没有更好的方法来设置超时并取消下载过程
PS: CreatePdfZip 方法需要时间。
为避免此错误,您可以检查response
是否已发送,只有在未发送时才发送响应(但不会真正solve/cancel下载处理)
...
fs.readFile(fullzipPath, (err2, zipData) => {
if (err2) reject(err2);
if (!res.headersSent) {
const base64 = zipData.toString('base64');
res.setHeader('Content-type', 'application/zip');
res.type('zip');
res.end(base64, 'binary');
console.log('EXCELLENT');
}
});
...
我正在下载一个文件,有时文件很大,超时时间不够。超时时,我想取消下载过程,因为即使出现超时错误,它也会继续处理文件并给出以下异常
_http_outgoing.js:470 throw new ERR_HTTP_HEADERS_SENT('set'); ^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:470:11)
这是我的异步方法
router.get('/api/files/GetFile', urlencodedParser, (req, res) => {
return new Promise(function (resolve, reject) {
(async function () {
try {
var folderName = "File_" + moment().format('DD-MM-YYYY HH_mm_ss');
await routerFile.CreatePdfZip(req.query.VoucherCodes, req.query.AppNames, folderName);
var fullzipPath = './FilesToDownload/' + folderName + '.zip';
zipFolder('./FilesToDownload/' + folderName, './FilesToDownload/' + folderName + '.zip', function (err) {
if (err) {
return reject(err);
} else {
console.log('zip created');
rimraf('./FilesToDownload/' + folderName, function () {
console.log("folder has been deleted");
});
fs.readFile(fullzipPath, (err2, zipData) => {
if (err2) reject(err2);
const base64 = zipData.toString('base64');
res.setHeader('Content-type', 'application/zip');
res.type('zip');
res.end(base64, 'binary');
console.log('EXCELLENT');
});
}
});
} catch (error) {
return reject(error);
}
})();
}).catch(error => {
console.log(error);
res.send(error);
});
});
错误发生在res.setHeader('Content-type','application/zip');
行PS: 路由器变量来自 const router = express.Router();
这里是超时设置
const app = express();
app.use(timeout('2s'));
app.use(bodyParser());
app.use(haltOnTimedout);
app.use(cookieParser());
app.use(haltOnTimedout);
function haltOnTimedout(req, res, next) {
if (!req.timedout)
next();
else {
console.log('TIMEOUT.----------------------------------------------');
}
}
我在这里做错了什么?或者有没有更好的方法来设置超时并取消下载过程
PS: CreatePdfZip 方法需要时间。
为避免此错误,您可以检查response
是否已发送,只有在未发送时才发送响应(但不会真正solve/cancel下载处理)
...
fs.readFile(fullzipPath, (err2, zipData) => {
if (err2) reject(err2);
if (!res.headersSent) {
const base64 = zipData.toString('base64');
res.setHeader('Content-type', 'application/zip');
res.type('zip');
res.end(base64, 'binary');
console.log('EXCELLENT');
}
});
...