Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

200
Views
Cómo procesar cada fila/búfer de forma síncrona al leer un archivo de forma asíncrona mediante una secuencia

como puede ver, tengo un js que toma un .csv y llama a una función asíncrona para cada fila (4 funciones diferentes de forma iterativa).

El problema es que necesito esperar el final de la función en la i-ésima iteración antes de continuar con la iteración i+1 .

 const csv = require('csv-parser'); const fs = require('fs'); var i=1; fs.createReadStream('table.csv') .pipe(csv()) .on('data', (row) => { switch(i%4){ case 1: org1createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; case 2: org2createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; case 3: org3createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; case 0: org4createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; } i++; }) .on('end', () => { console.log('CSV file successfully processed'); }); async function org1createPatient(patientId, FirstName, LastName, Age, Sex, ChestPainType, RestingBP, Cholesterol, FastingBS, RestingECG, MaxHR, ExerciseAngina, Oldpeak, ST_Slope, HeartDisease) { ... } async function org2createPatient( patientId, FirstName, LastName, Age, Sex, ChestPainType, RestingBP, Cholesterol, FastingBS, RestingECG, MaxHR, ExerciseAngina, Oldpeak, ST_Slope, HeartDisease) { ... } async function org3createPatient( patientId, FirstName, LastName, Age, Sex, ChestPainType, RestingBP, Cholesterol, FastingBS, RestingECG, MaxHR, ExerciseAngina, Oldpeak, ST_Slope, HeartDisease) { ... } async function org4createPatient( patientId, FirstName, LastName, Age, Sex, ChestPainType, RestingBP, Cholesterol, FastingBS, RestingECG, MaxHR, ExerciseAngina, Oldpeak, ST_Slope, HeartDisease) { ... }

¿Cómo puedo conseguir lo que quiero? ¡Espero que mi pregunta sea lo suficientemente clara!

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

El readStream que está utilizando aquí es asíncrono, lo que significa que .on(event, callback) se activará cada vez que se lea un nuevo dato, independientemente de cualquier callback de llamada activada. En otras palabras, la ejecución de la función de callback de llamada aquí no afecta este proceso, se ejecutará en paralelo cada vez que se reciba un event .

Esto significa que, en caso de que la callback de llamada fuera a ejecutar un fragmento de código que es asíncrono, es muy posible que termine en una situación en la que aún se estén ejecutando varias instancias de esta función en el momento en que se reciba el siguiente event lectura.

Nota: esto es válido para cualquier evento, incluido el evento 'end' .

Si tuviera que usar async/await en la callback de llamada, solo haría que la lógica interna de esta función fuera sincrónica. Todavía no afectaría la velocidad a la que se leen sus datos.

Para hacerlo, querrá usar async/await en la callback de llamada (para que sea sincrónico internamente) y hacer que la callback de llamada pause y reanude manualmente la operación de lectura en paralelo.

 const csv = require('csv-parser'); const fs = require('fs'); let i = 1; const stream = fs.createReadStream('table.csv').pipe(csv()); stream.on('data', async (row) => { // pause overall stream until this row is processed stream.pause(); // process row switch (i%4){ case 1: await org1createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; case 2: await org2createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; case 3: await org3createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; case 0: await org4createPatient(row.patientId, row.FirstName, row.LastName, row.Age, row.Sex, row.ChestPainType, row.RestingBP, row.Cholesterol, row.FastingBS, row.RestingECG, row.MaxHR, row.ExerciseAngina, row.Oldpeak, row.ST_Slope, row.HeartDisease); break; } i++; // resume overall stream stream.resume(); }); stream.on('end', () => { // now guaranteed that no instances of `callback` is still running in parallel when this event is fired console.log('CSV file successfully processed'); });
about 4 years ago · Juan Pablo Isaza Report

0

La solución a continuación es usar la biblioteca iter-ops , que es muy eficiente en este caso, porque pipe(csv()) devuelve un AsyncIterable , por lo que debe procesarse en consecuencia.

Como no le importa lo que devuelvan esas funciones de procesamiento, podemos limitar el procesamiento de cada fila:

 const {pipe, throttle, onEnd, catchError} = require('iter-ops'); const csv = require('csv-parser'); const fs = require('fs'); const asyncIterable = fs.createReadStream('table.csv').pipe(csv()); const i = pipe( asyncIterable, throttle(async (row, index) => { switch (index % 4) { case 1: await org1createPatient(row.patientId, ...); break; case 2: await org2createPatient(row.patientId, ...); break; case 3: await org3createPatient(row.patientId, ...); break; case 0: await org4createPatient(row.patientId, ...); break; default: break; } }), onEnd(s => { console.log(`Completed ${s.count} rows, in ${s.duration}ms`); }), catchError((err, ctx) => { console.log(`Failed on row with index ${ctx.index}:`, err); throw err; // to stop the iteration }) ); async function processCSV() { // this will trigger the iteration: for await(const a of i) { // iterate and process the CSV } }

PD: soy el autor de iter-ops .

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!