En NodeJS, necesito hacer una función similar a grep para fines de investigación de registros y estoy tratando de hacerlo usando readline (ya que no quiero readline-sync). He leído muchos mensajes, tutoriales, documentación, publicaciones de stackoverflow, etc., pero no podía entender cómo hacerlo funcionar.
const grep = async function(pattern, filepath){ return new Promise((resolve, reject)=>{ let regex = new RegExp(pattern); let fresult = ``; let lineReader = require(`readline`).createInterface({ input: require(`fs`).createReadStream(filepath) }); lineReader.on(`line`, function (line) { if(line.match(regex)){ fresult += line; } }); resolve(fresult); }); } let getLogs = await grep(/myregex/gi, filepath); console.log(getLogs);Lo que me da:
SyntaxError: await solo es válido en funciones asíncronas y los cuerpos de módulos de nivel superior
¿Dónde estoy equivocado? Siento que soy bueno pero cometí un error de principiante que es bailar justo debajo de mis ojos.
Lo que se han perdido las otras respuestas es que tiene dos problemas en su código.
La espera de nivel superior ( await no envuelta en una función async ) solo es posible cuando se ejecuta Node.js "como un módulo ES", que es cuando está utilizando import {xyz} from 'module' en lugar de const {xyz} = require('module') .
Como se mencionó, una forma de solucionar esto es envolverlo en una función asíncrona:
// Note: You omitted the ; on line 18 (the closing } bracket) // which will cause an error, so add it. (async () => { let getLogs = await grep(/myregex/gi, filepath); console.log(getLogs); })(); Una opción diferente es guardar su archivo como .mjs , no como .js . Esto significa que debe usar import en lugar de require .
La tercera opción es crear un package.json y especificar "type": "module" . Se aplican las mismas reglas.
Cuando llame a resolve() , el controlador de eventos en lineReader.on('line') aún no se habrá ejecutado. Esto significa que se resolverá en una cadena vacía y no en la entrada del usuario. Después de todo, declarar una función async no hace nada para esperar eventos/devoluciones de llamada.
Puede resolver esto esperando el evento 'cerrar' de Readline y solo luego resolver la promesa.
const grep = async function(pattern, filepath){ return new Promise((resolve, reject)=>{ let regex = new RegExp(pattern); let fresult = ``; let lineReader = require(`readline`).createInterface({ input: require(`fs`).createReadStream(filepath) }); lineReader.on(`line`, function (line) { if(line.match(regex)){ fresult += line; } }); // Wait for close/error event and resolve/reject lineReader.on('close', () => resolve(fresult)); lineReader.on('error', reject); }); }; // ";" was added (async () => { let getLogs = await grep(/myregex/gi, 'foo'); console.log("output", getLogs); })(); El módulo de events tiene una práctica función de utilidad nombrada once que le permite escribir su código de una manera más breve y clara:
const { once } = require('events'); // If you're using ES Modules use: // import { once } from 'events' const grep = async function(pattern, filepath){ // Since the function is 'async', no need for // 'new Promise()' let regex = new RegExp(pattern); let fresult = ``; let lineReader = require(`readline`).createInterface({ input: require(`fs`).createReadStream(filepath) }); lineReader.on(`line`, function (line) { if(line.match(regex)){ fresult += line; } }); // Wait for the first 'close' event // If 'lineReader' emits an 'error' event, this // will throw an exception with the error in it. await once(lineReader, 'close'); return fresult; }; (async () => { let getLogs = await grep(/myregex/gi, 'foo'); console.log("output", getLogs); })(); // If you're using ES Modules: // leave out the (async () => { ... })();prueba esto:
async function run(){ let getLogs = await grep(/myregex/gi, `/`); console.log(getLogs); } run();