← Sandbox SDK / sandbox / guides
Потоковый вывод
В этом руководстве показано, как обрабатывать вывод в реальном времени от команд, процессов и выполнения кода.
Когда использовать потоковую передачу
Используйте потоковую передачу, когда вам нужно:
- Обратная связь в реальном времени - Отображение прогресса по мере его выполнения
- Долго выполняющиеся операции - Сборки, тесты, установки, которые занимают время
- Интерактивные приложения - Чат-боты, выполнение кода, живые демонстрации
- Большой объём вывода - Обработка вывода по частям, а не целиком
- Пользовательский опыт - Избавляет пользователей от ожидания без обратной связи
Используйте нестриминговый режим (exec()) для:
- Быстрые операции - Команды, которые выполняются за секунды
- Небольшой объём вывода - Когда вывод легко помещается в память
- Постобработка - Когда нужен полный вывод перед обработкой
Потоковое выполнение команд
Используйте execStream() чтобы получать вывод в реальном времени:
import { getSandbox, parseSSEStream } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
const stream = await sandbox.execStream("npm run build");
for await (const event of parseSSEStream(stream)) {
switch (event.type) {
case "stdout":
console.log(event.data);
break;
case "stderr":
console.error(event.data);
break;
case "complete":
console.log("Exit code:", event.exitCode);
break;
case "error":
console.error("Failed:", event.error);
break;
}
}import { getSandbox, parseSSEStream, type ExecEvent } from '@cloudflare/sandbox';
const sandbox = getSandbox(env.Sandbox, 'my-sandbox');
const stream = await sandbox.execStream('npm run build');
for await (const event of parseSSEStream<ExecEvent>(stream)) {
switch (event.type) {
case 'stdout':
console.log(event.data);
break;
case 'stderr':
console.error(event.data);
break;
case 'complete':
console.log('Exit code:', event.exitCode);
break;
case 'error':
console.error('Failed:', event.error);
break;
}
}Потоковая передача клиенту
Возврат потокового вывода пользователям через Server-Sent Events:
import { getSandbox } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox";
export default {
async fetch(request, env) {
const sandbox = getSandbox(env.Sandbox, "builder");
const stream = await sandbox.execStream("npm run build");
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
},
});
},
};import { getSandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const sandbox = getSandbox(env.Sandbox, 'builder');
const stream = await sandbox.execStream('npm run build');
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache'
}
});
}
};Использование на стороне клиента:
// Browser JavaScript
const eventSource = new EventSource("/build");
eventSource.addEventListener("stdout", (event) => {
const data = JSON.parse(event.data);
console.log(data.data);
});
eventSource.addEventListener("complete", (event) => {
const data = JSON.parse(event.data);
console.log("Exit code:", data.exitCode);
eventSource.close();
});// Browser JavaScript
const eventSource = new EventSource('/build');
eventSource.addEventListener('stdout', (event) => {
const data = JSON.parse(event.data);
console.log(data.data);
});
eventSource.addEventListener('complete', (event) => {
const data = JSON.parse(event.data);
console.log('Exit code:', data.exitCode);
eventSource.close();
});Потоковая передача журналов процесса
Мониторинг вывода фонового процесса:
import { parseSSEStream } from "@cloudflare/sandbox";
const process = await sandbox.startProcess("node server.js");
const logStream = await sandbox.streamProcessLogs(process.id);
for await (const log of parseSSEStream(logStream)) {
console.log(log.data);
if (log.data.includes("Server listening")) {
console.log("Server is ready");
break;
}
}import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
const process = await sandbox.startProcess('node server.js');
const logStream = await sandbox.streamProcessLogs(process.id);
for await (const log of parseSSEStream<LogEvent>(logStream)) {
console.log(log.data);
if (log.data.includes('Server listening')) {
console.log('Server is ready');
break;
}
}Обработка ошибок
Проверяйте коды завершения и обрабатывайте ошибки потока:
const stream = await sandbox.execStream("npm run build");
for await (const event of parseSSEStream(stream)) {
switch (event.type) {
case "stdout":
console.log(event.data);
break;
case "error":
throw new Error(`Build failed: ${event.error}`);
case "complete":
if (event.exitCode !== 0) {
throw new Error(`Build failed with exit code ${event.exitCode}`);
}
break;
}
}const stream = await sandbox.execStream('npm run build');
for await (const event of parseSSEStream<ExecEvent>(stream)) {
switch (event.type) {
case 'stdout':
console.log(event.data);
break;
case 'error':
throw new Error(`Build failed: ${event.error}`);
case 'complete':
if (event.exitCode !== 0) {
throw new Error(`Build failed with exit code ${event.exitCode}`);
}
break;
}
}Рекомендации
- Всегда полностью считывайте потоки - Не допускайте зависания непрочитанных потоков
- Обработка всех типов событий - Обработка событий stdout, stderr, complete и error
- Проверка кодов завершения - Ненулевой код завершения означает ошибку
- Оставить отзыв - Отображение прогресса пользователям при длительных операциях
Дополнительные материалы
- Справочник по Commands API - Полный API потоковой передачи
- Руководство по выполнению команд - Шаблоны выполнения команд
- Руководство по фоновым процессам - Потоковая передача логов процесса
- Руководство по Code Interpreter - Потоковая передача вывода выполнения кода