Можно ли на Express.js
отправить ответ порцией данных? Я пробовал (онлайн-демо):
const express = require('express');
const app = express();
const port = 3111;
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
app.get('/', async (req, res) => {
res.setHeader('Content-Type', 'application/json');
// flush to enable stream
res.flushHeaders();
res.write('[');
for (let i = 1; i <= 1000; i++) {
res.write(JSON.stringify(`data ${i}`));
if (i + 1 <= 1000) {
res.write(',');
}
await sleep(1);
}
res.write(']');
res.end();
});
app.listen(port, () => {
console.info(`App is live at http://localhost:${port}`);
});
Но и в Google Chrome, и в Postman ответ отображается только при вызове res.end()
.
Есть некоторые соображения
Content-Type
для таких потоков, как application/stream+json
.res.flushHeaders()
, поскольку Express
автоматически обрабатывает его, когда вы начинаете писать тело ответа.import express from "express";
const app = express();
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
app.get('/stream', async (_req, res) => {
res.setHeader('Content-Type', 'application/stream+json');
res.write('[');
for (let i = 1; i <= 1000; i++) {
res.write(JSON.stringify(`data ${i}`));
if (i < 1000) {
res.write(",");
}
await sleep(1); // Simulates a delay
}
res.write(']');
res.end();
});
const port = 3000;
app.listen(port, () => {
console.info(`Server running on http://localhost:${port}`);
});
При использовании netcat
темп возвращаемых данных кажется правильным, и это фрагмент закодирован.
echo -ne 'GET /stream HTTP/1.1\n\n' | netcat localhost 8080
Пример вывода:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json
Date: Mon, 06 May 2024 08:58:26 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
1
[
8
"data 1"
1
,
8
"data 2"
1
,
8
"data 3"
1
,
8
"data 4"