Estoy intentando leer una secuencia línea por línea y para cada línea hago un procesamiento asíncrono. El problema que tengo es cómo determinar cuándo se completan las operaciones para todas las líneas. Pensé que podría usar el evento "cerrar" readline, pero parece que se desencadena mucho antes de que se completen las operaciones asíncronas que comencé en el evento "línea".

Aquí están los controladores de eventos en cuestión:

logReader.on("line", inputLine => {
    self._processLogLine(inputLine, () => {
        if (self.streamFinished) {
            completionCallback(err);
        }
    });
});

logReader.on("close", () => {
    self.streamFinished = true;
});

El método completeCallback debe llamarse cuando se realiza todo el procesamiento de línea en la secuencia.

He pensado en agregar contadores para las operaciones de línea iniciadas / completadas y llamar a la terminación Callback cuando coinciden, pero eso parece incómodo.

0
Fred Strauss 27 oct. 2017 a las 21:16

3 respuestas

La mejor respuesta

Aquí hay una forma en que podría hacerlo básicamente haciendo un seguimiento del éxito de cada línea. No tengo suficiente código para probarlo ...

const lineProcessing = [];

const doCompletion = () => {
  if (self.streamFinished && !lineProcessing.includes(false)) {
    // Not sure where 'err' comes from
    completionCallback(err);
  }
}

logReader.on("line", inputLine => {
  lineProcessing.push(false);
  let processingIndex = lineProcessing.length - 1;
  self._processLogLine(inputLine, () => {
    lineProcessing[processingIndex] = true;
    doCompletion();
  });
});

logReader.on("close", () => {
  self.streamFinished = true;
});
1
Chris Phillips 27 oct. 2017 a las 18:32

Es un poco difícil saber con certeza lo que debe suceder sin más contexto. Pero aquí hay una solución rápida y un tanto sucia que debería adaptarse a su situación. Muestra cómo puedes lograr esto con promesas:

let promises = []

logReader.on("line", inputLine => {
    promises.push(new Promise(resolve => {
        self._processLogLine(inputLine, resolve)
    })
})

logReader.on("close", () => {
    Promise.all(promises)
        .then(completionCallback)
})

Esencialmente, solo cree una serie de promesas. Cuando sepa que se han agregado todas las promesas a la matriz, llame a Promise.all() en él.

Si utiliza este enfoque, probablemente desee agregar comprobación de errores (rechazando y captura).

1
bowheart 27 oct. 2017 a las 18:36

Mira en los generadores. Le dan una manera de hacer un bucle "for" ... y cuando haya terminado, simplemente regresará de la función de generador.

Por lo tanto, puede tener un generador para leer el archivo y una función que use el generador, luego, cuando finalice el ciclo, llame a su devolución de llamada.

0
theGleep 27 oct. 2017 a las 18:34