为什么节点会抱怨未关闭的文件描述符,即使我正在关闭所有句柄?

问题描述 投票:0回答:2

我有一个异步函数,它创建一个读取流并将其写入http响应,如下所示:

    let handle = await getFile();
    let stream = handle.createReadStream();
    let stat = await handle.stat();
    res.setHeader("content-length", stat.size);
    res.setHeader("content-type", "application/octet");
    res.statusCode = 200;
    stream.pipe(res);
    stream.on('close', () => {
      handle.close();
      res.end();
    });

如您所见,我在流关闭时关闭句柄,并结束响应以达到良好的效果。然而,我偶尔会看到节点记录此信息:

(node:54119) Warning: Closing file descriptor 21 on garbage collection
(Use `node --trace-warnings ...` to show where the warning was created)
(node:54119) [DEP0137] DeprecationWarning: Closing a FileHandle object on garbage collection is deprecated. Please close FileHandle objects explicitly using FileHandle.prototype.close(). In the future, an error will be thrown if a file descriptor is closed during garbage collection.

我的 HTTP 响应中没有错误,并且我已经通过日志验证了每个请求都会调用我的

handle.close()
。为什么节点认为我有未关闭的文件描述符?

node.js garbage-collection filehandle
2个回答
0
投票

这是因为我的异步函数在流完成写入之前返回。我通过用承诺包裹它并等待它来修复它: let handle = await getFile(); let stream = handle.createReadStream(); let stat = await handle.stat(); res.setHeader("content-length", stat.size); res.setHeader("content-type", "application/octet"); res.statusCode = 200; await new Promise<void>((resolve, reject) => { stream.pipe(res); stream.on('close', () => { handle.close(); res.end(); resolve(); }); });



0
投票
handle.close()

返回一个 Promise。因此,即使等待

handle.close()
也是一种有效的方法。
let handle = await getFile();
let stream = handle.createReadStream();
let stat = await handle.stat();

res.setHeader("content-length", stat.size);
res.setHeader("content-type", "application/octet");
res.statusCode = 200;
stream.pipe(res);
stream.on('close', async () => {
  await handle.close();
  res.end();
});

© www.soinside.com 2019 - 2024. All rights reserved.