function createCSVScanner(onRow, cols) { let buffer = ''; return function scanChunk(chunk) { buffer += chunk; const lines = buffer.split('\n'); buffer = lines.pop(); // Save incomplete line for (const line of lines) { const fields = []; let start = 0; let col = 0; for (let i = 0; i < line.length; i++) { if (line[i] === ',' && col < cols) { fields.push(line.slice(start, i)); start = i + 1; col++; } } fields.push(line.slice(start, line.length-1)); onRow(...fields); } }; } export default async function(url, nonJsonCols, onRow) { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const reader = response.body.getReader(); const decoder = new TextDecoder("utf-8"); const scanner = createCSVScanner(onRow, nonJsonCols); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); scanner(chunk); } }