英文:
Readable to Buffer function doesn't work because Readable doesn't emit `end` event
问题
以下是您要翻译的内容:
所以我有一个典型的`streamToBuffer`函数:
```js
const streamToBuffer = async (stream: NodeJS.ReadableStream): Promise<Buffer> => {
const chunks: Buffer[] = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk: WithImplicitCoercion<ArrayBuffer | SharedArrayBuffer>) =>
chunks.push(Buffer.from(chunk)),
);
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
});
};
就我所知,这是将流转换为缓冲区的NodeJS中通常的方式。
嗯,有一些情况下end
事件不会发生。error
或close
事件也不会发生。只会触发data
事件,然后Promise永远不会被解析/拒绝。
这可能是如何发生的呢?
我认为唯一发生这种情况的情况是使用node-fetch
库获取文件时。
const getBinary = async (id: string) => {
return await fetch(`带有id的内部URL`, {
method: 'GET',
})
.then(async (response) => {
switch (response.status) {
case 200:
return new Readable().wrap(response.body!); // <-- 这个Readable
case 404:
throw new NotFound(await response.json());
default:
throw a BadGateway(await response.json());
}
})
.catch((err) => {
throw a InternalServerError(err);
});
};
我不完全确定这个问题是否只会在像这样获取的流中发生。但就我所能了解,似乎是这样。请注意,并非每次都会发生,只有对于某些id
值,某些二进制文件。
一些额外信息:如果我使用浏览器导航或使用curl访问任何存在问题的URL,一切都正常。我可以毫无问题地获取文件。
<details>
<summary>英文:</summary>
So I have a typical `streamToBuffer` function:
```js
const streamToBuffer = async (stream: NodeJS.ReadableStream): Promise<Buffer> => {
const chunks: Buffer[] = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk: WithImplicitCoercion<ArrayBuffer | SharedArrayBuffer>) =>
chunks.push(Buffer.from(chunk)),
);
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
});
};
It's, as far as I know, the usual way of transforming streams into buffers in NodeJS.
Well, there are some instances where the end
event doesn't happen. Neither does error
or close
. Just data
event is fired and the promise then never gets resolved/rejected.
How could that be possible?
I think the only situations when this happens are when retrieving a file using the node-fetch
library.
const getBinary = async (id: string) => {
return await fetch(`an internal URL with the id`, {
method: 'GET',
})
.then(async (response) => {
switch (response.status) {
case 200:
return new Readable().wrap(response.body!); // <-- This Readable
case 404:
throw new NotFound(await response.json());
default:
throw new BadGateway(await response.json());
}
})
.catch((err) => {
throw new InternalServerError(err);
});
};
I'm not 100% sure if the issue only happens with a stream obtained like this. But to the best of my ability it appears it is the case. Mind you, not every time. Only for some id
values, so certain binaries.
Some extra information: if I navigate with my browser or use curl with any of the problematic URLs everything works fine. I get the file with no issues.
答案1
得分: 1
If you read the doc for readable.wrap()
it is not meant for the type of stream in response.body
. fetch()
returns a WebStream, not the old style nodejs stream that .wrap()
is meant to be used with.
在查看readable.wrap()
的文档时,它并不适用于response.body
中的流类型。fetch()
返回的是WebStream,而不是.wrap()
旨在与旧式的nodejs流一起使用的类型。
In recent versions of nodejs, you can use Readable.fromWebStream(webStream)
to convert from a webStream to a nodejs Readable stream. Nodejs doc.
在较新版本的nodejs中,您可以使用Readable.fromWebStream(webStream)
将webStream转换为nodejs可读流。Nodejs 文档。
return Readable.fromWeb(response.body);
这里是一个示例:https://css-tricks.com/web-streams-everywhere-and-fetch-for-node-js/#aa-node-streams-interoperability。
在较旧版本的nodejs中,您可以使用支持直接将响应作为nodejs读取流获取的http请求库,如got
或axios
。
const readStream = got.stream(url);
英文:
If you read the doc for readable.wrap()
it is not meant for the type of stream in response.body
. fetch()
returns a WebStream, not the old style nodejs stream that .wrap()
is meant to be used with.
In recent versions of nodejs, you can use Readable.fromWebStream(webStream)
to convert from a webStream to a nodejs Readable stream. Nodejs doc.
return Readable.fromWeb(response.body);
Here's an example: https://css-tricks.com/web-streams-everywhere-and-fetch-for-node-js/#aa-node-streams-interoperability.
In older versions of nodejs, you can use an http request library like got
or axios
that directly supports getting a response as a nodejs readstream.
const readStream = got.stream(url);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论