Mi programa Node.js, que es un programa de línea de comandos ordinario que, en general, no hace nada operacionalmente inusual, nada específico del sistema o asíncrono ni nada por el estilo, necesita escribir mensajes en un archivo de vez en cuando, y luego se interrumpirá con ^C y necesita que el contenido del archivo aún esté allí.
Intenté usar fs.createWriteStream pero eso solo termina con un archivo de 0 bytes. (El archivo contiene texto si el programa termina ejecutándose al final del archivo principal, pero ese no es el escenario que tengo).
Intenté usar winston pero eso termina sin crear el archivo. (El archivo contiene texto si el programa termina ejecutándose al final del archivo principal, pero ese no es el escenario que tengo).
Y fs.writeFile funciona perfectamente cuando tiene todo el texto que desea escribir al principio, pero no parece admitir agregar una línea a la vez.
cual es la manera recomendada para hacer esto?
Editar: código específico que he probado:
var fs = require('fs') var log = fs.createWriteStream('test.log') for (var i = 0; i < 1000000; i++) { console.log(i) log.write(i + '\n') }Ejecute durante unos segundos, presione ^ C, deja un archivo de 0 bytes.
¡Resulta que Node proporciona una API de E/S de archivo de nivel inferior que parece funcionar bien!
var fs = require('fs') var log = fs.openSync('test.log', 'w') for (var i = 0; i < 100000; i++) { console.log(i) fs.writeSync(log, i + '\n') }NodeJS no funciona de la manera tradicional. Utiliza un solo subproceso, por lo que al ejecutar un bucle grande y realizar E/S en el interior, no le está dando la oportunidad (es decir, liberar la CPU) de realizar otras operaciones asíncronas, por ejemplo: vaciar el búfer de memoria al archivo real.
La lógica debe ser: haga una write , luego pase su función (que invoca la escritura) como una devolución de llamada a process.nextTick o como una devolución de llamada al evento de drain del flujo de escritura (si el búfer estaba lleno durante la última escritura).
Aquí hay una versión rápida y sucia que hace lo que necesita. Tenga en cuenta que no hay bucles de ejecución prolongada u otros bloqueos de la CPU, sino que programo mis escrituras posteriores para el futuro y vuelvo rápidamente, liberando momentáneamente la CPU para otras cosas.
var fs = require('fs') var log = fs.createWriteStream('test.log'); var i = 0; function my_write() { if (i++ < 1000000) { var res = log.write("" + i + "\r\n"); if (!res) { log.on('drain',my_write); } else { process.nextTick(my_write); } console.log("Done" + i + " " + res + "\r\n"); } } my_write();Esta función también podría ser útil.
/** * Write `data` to a `stream`. if the buffer is full will block * until it's flushed and ready to be written again. * [see](https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback) */ export function write(data, stream) { return new Promise((resolve, reject) => { if (stream.write(data)) { process.nextTick(resolve); } else { stream.once("drain", () => { stream.off("error", reject); resolve(); }); stream.once("error", reject); } }); }