← Cloudflare Workers / workers / examples
Потоковая передача большого JSON
Используйте Streams API для обработки данных JSON, которые превысили бы лимит памяти Worker в 128 МБ при полной буферизации. Потоковая обработка позволяет разбирать и преобразовывать данные JSON по мере их поступления. Это быстрее, чем буферизация всей полезной нагрузки в памяти, поскольку Worker может начать обработку данных постепенно, а также позволяет Worker обрабатывать многогигабайтные данные или файлы в пределах лимита памяти.
@streamparser/json-whatwg ↗ библиотека предоставляет потоковый парсер JSON, совместимый с Web Streams API.
Установите зависимость:
npm install @streamparser/json-whatwgПотоковая передача тела запроса в формате JSON
В этом примере выполняется разбор большого тела JSON-запроса и извлечение отдельных полей без загрузки всего содержимого в память.
import { JSONParser } from "@streamparser/json-whatwg";
export default {
async fetch(request): Promise<Response> {
const parser = new JSONParser({ paths: ["$.users.*"] });
const users: string[] = [];
// Pipe the request body through the JSON parser
const reader = request.body
.pipeThrough(parser)
.getReader();
// Process matching JSON values as they stream in
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Extract only the name field from each user object
if (value.value?.name) {
users.push(value.value.name);
}
}
return Response.json({ userNames: users });
},
} satisfies ExportedHandler;import { JSONParser } from "@streamparser/json-whatwg";
export default {
async fetch(request) {
const parser = new JSONParser({ paths: ["$.users.*"] });
const users = [];
// Pipe the request body through the JSON parser
const reader = request.body
.pipeThrough(parser)
.getReader();
// Process matching JSON values as they stream in
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Extract only the name field from each user object
if (value.value?.name) {
users.push(value.value.name);
}
}
return Response.json({ userNames: users });
},
};Потоковая передача и преобразование ответа в формате JSON
В этом примере выполняется получение большого JSON-ответа от вышестоящего API, преобразование отдельных полей и потоковая передача изменённого ответа клиенту.
import { JSONParser } from "@streamparser/json-whatwg";
export default {
async fetch(request): Promise<Response> {
const response = await fetch("https://api.example.com/large-dataset.json");
const parser = new JSONParser({ paths: ["$.items.*"] });
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
const encoder = new TextEncoder();
// Process the upstream response in the background
(async () => {
const reader = response.body
.pipeThrough(parser)
.getReader();
await writer.write(encoder.encode('{"processedItems":['));
let first = true;
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Transform each item as it streams through
const item = value.value;
const transformed = {
id: item.id,
title: item.title.toUpperCase(),
processed: true,
};
if (!first) await writer.write(encoder.encode(","));
first = false;
await writer.write(encoder.encode(JSON.stringify(transformed)));
}
await writer.write(encoder.encode("]}"));
await writer.close();
})();
return new Response(readable, {
headers: { "Content-Type": "application/json" },
});
},
} satisfies ExportedHandler;import { JSONParser } from "@streamparser/json-whatwg";
export default {
async fetch(request) {
const response = await fetch("https://api.example.com/large-dataset.json");
const parser = new JSONParser({ paths: ["$.items.*"] });
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
const encoder = new TextEncoder();
// Process the upstream response in the background
(async () => {
const reader = response.body
.pipeThrough(parser)
.getReader();
await writer.write(encoder.encode('{"processedItems":['));
let first = true;
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Transform each item as it streams through
const item = value.value;
const transformed = {
id: item.id,
title: item.title.toUpperCase(),
processed: true,
};
if (!first) await writer.write(encoder.encode(","));
first = false;
await writer.write(encoder.encode(JSON.stringify(transformed)));
}
await writer.write(encoder.encode("]}"));
await writer.close();
})();
return new Response(readable, {
headers: { "Content-Type": "application/json" },
});
},
};Дополнительные материалы
- Streams API - Узнайте больше о стриминге в Workers
- TransformStream - Создавайте собственные преобразования потоков
- @streamparser/json-whatwg ↗ - Документация по потоковому парсеру JSON