This tutorial will guide you through using web-csv-toolbox's worker thread execution to improve performance and maintain UI responsiveness.
By the end of this tutorial, you'll be able to:
Worker threads allow you to run CPU-intensive tasks off the main thread, keeping your application responsive. For CSV parsing, this means:
✅ Use workers when:
❌ Skip workers when:
stable preset instead)Note: Workers add communication overhead (data transfer between threads), which may increase execution time. However, they keep the UI responsive, making them ideal for browser applications.
The simplest way to use workers is with the engine option:
import { parse } from 'web-csv-toolbox';
const csv = `name,age,city
Alice,30,New York
Bob,25,San Francisco
Charlie,35,Los Angeles`;
// Parse using worker thread
for await (const record of parse(csv, {
engine: { worker: true }
})) {
console.log(record);
}
What happens:
Instead of manually configuring the engine, you can use predefined presets:
import { parse, EnginePresets } from 'web-csv-toolbox';
const csv = `name,age,city
Alice,30,New York
Bob,25,San Francisco`;
// Use the 'balanced' preset (recommended for production)
for await (const record of parse(csv, {
engine: EnginePresets.balanced()
})) {
console.log(record);
}
| Preset | Optimization Target | Worker | WASM | Stability |
|---|---|---|---|---|
stable |
Stability | ❌ | ❌ | ⭐ Most Stable |
responsive |
UI responsiveness | ✅ | ❌ | ✅ Stable |
memoryEfficient |
Memory efficiency | ✅ | ❌ | ⚠️ Experimental |
fast |
Parse speed | ❌ | ✅ | ✅ Stable |
responsiveFast |
UI responsiveness + parse speed | ✅ | ✅ | ✅ Stable |
balanced |
Balanced (general-purpose) | ✅ | ❌ | ✅ Stable |
Recommendation: Use EnginePresets.balanced() for general-purpose CSV processing. It provides non-blocking execution with WHATWG Encoding Standard encodings support and has automatic stable fallback on Safari.
Workers are especially useful for parsing CSV from network responses:
import { parseResponse, EnginePresets } from 'web-csv-toolbox';
async function fetchAndParseCSV(url: string) {
const response = await fetch(url);
// Parse response using worker
for await (const record of parseResponse(response, {
engine: EnginePresets.balanced()
})) {
console.log(record);
}
}
// Usage
await fetchAndParseCSV('https://example.com/large-data.csv');
Benefits:
When parsing multiple CSV files, use a worker pool (ReusableWorkerPool) to limit resource usage:
import { parse, ReusableWorkerPool } from 'web-csv-toolbox';
// Create a worker pool with max 4 concurrent workers
using pool = new ReusableWorkerPool({ maxWorkers: 4 });
const csvFiles = [
'data1.csv',
'data2.csv',
'data3.csv',
'data4.csv',
];
// Parse multiple files concurrently
await Promise.all(
csvFiles.map(async (filename) => {
const csv = await Deno.readTextFile(filename);
for await (const record of parse(csv, {
engine: {
worker: true,
workerPool: pool
}
})) {
console.log(`${filename}:`, record);
}
})
);
// Pool is automatically disposed when leaving the 'using' block
Key Points:
using keyword ensures proper cleanupmaxWorkersAlways wrap worker parsing in try-catch blocks:
import { parse, EnginePresets } from 'web-csv-toolbox';
async function parseWithErrorHandling(csv: string) {
try {
for await (const record of parse(csv, {
engine: EnginePresets.balanced()
})) {
console.log(record);
}
} catch (error) {
if (error instanceof Error) {
console.error('Parsing failed:', error.message);
}
}
}
Common Errors:
You can create custom configurations based on presets:
import { parse, EnginePresets } from 'web-csv-toolbox';
// Customize a preset with additional options
for await (const record of parse(csv, {
engine: EnginePresets.balanced({
workerPool: myPool,
onFallback: (info) => console.log('Fallback occurred:', info)
})
})) {
console.log(record);
}
Available Preset Options:
workerPool: Shared ReusableWorkerPool instanceworkerURL: Custom worker script URLonFallback: Callback when fallback occursimport { parse, EnginePresets } from 'web-csv-toolbox';
async function handleFileUpload(file: File) {
const progressElement = document.getElementById('progress');
const resultsElement = document.getElementById('results');
progressElement.textContent = 'Parsing...';
try {
const csv = await file.text();
let count = 0;
// Parse in worker - UI stays responsive
for await (const record of parse(csv, {
engine: EnginePresets.balanced()
})) {
count++;
// Update UI every 100 records
if (count % 100 === 0) {
progressElement.textContent = `Parsed ${count} records...`;
}
// Process record
resultsElement.innerHTML += `<div>${JSON.stringify(record)}</div>`;
}
progressElement.textContent = `✓ Parsed ${count} records`;
} catch (error) {
progressElement.textContent = '✗ Error parsing CSV';
console.error(error);
}
}
// Attach to file input
document.getElementById('csv-file').addEventListener('change', (e) => {
const file = e.target.files?.[0];
if (file) handleFileUpload(file);
});
import { Hono } from 'hono';
import { parse, ReusableWorkerPool } from 'web-csv-toolbox';
const app = new Hono();
// Create shared worker pool
using pool = new ReusableWorkerPool({ maxWorkers: 4 });
app.post('/parse-csv', async (c) => {
const csv = await c.req.text();
const results = [];
try {
for await (const record of parse(csv, {
engine: {
worker: true,
workerPool: pool
}
})) {
results.push(record);
}
return c.json({ success: true, data: results });
} catch (error) {
return c.json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
}, 500);
}
});
export default app;
Performance Characteristics:
| Approach | UI Blocking | Worker Overhead | Stability | Best For |
|---|---|---|---|---|
| Main thread | ✅ Yes | ❌ None | ⭐ Most Stable | Server-side, blocking acceptable |
| Worker | ❌ No | ⚠️ Communication overhead | ✅ Stable | Browser, non-blocking required |
Key Trade-offs:
Note: Actual performance depends on many factors:
Recommendation: Choose based on your requirements (blocking vs non-blocking, stability) rather than file size alone. Benchmark your specific use case. See CodSpeed for measured performance across different scenarios.
Worker support varies by browser:
| Browser | Worker Threads | Stream Transfer | Auto-Fallback |
|---|---|---|---|
| Chrome | ✅ | ✅ | N/A |
| Firefox | ✅ | ✅ | N/A |
| Edge | ✅ | ✅ | N/A |
| Safari | ✅ | ❌ | ✅ (to message-streaming) |
Note: Safari automatically falls back to message-streaming (slightly slower but still functional).
Browser API Support:
For detailed browser compatibility information, see Supported Environments.
You've learned how to:
Problem: Error: "Worker threads are not supported"
Solution: Ensure you're using a supported environment:
Problem: Worker execution is slower than main thread
Solution:
EnginePresets.balanced() instead of manual configurationProblem: Different behavior in Safari
Solution:
For complete, working examples of worker-based CSV processing, see:
Need help? Open an issue on GitHub.