Nodejs> Gulp> through2> ¿Limitación a 16 archivos?

Ok, esto parece estar vinculado a la propiedad “highWaterMark” de through2. Básicamente, significa “no almacene más de x archivos, espere a que alguien lo consum y luego solo acepte otro lote de archivos”. Como funciona de esta forma por diseño, el fragmento de esta pregunta se está revisando. Debe haber una mejor manera de manejar muchos archivos.

Solución rápida, permitiendo 8000 archivos:

through.obj({ highWaterMark: 8000 }, (file, enc, next) => { ... }) 

Pregunta original

Estoy usando una tarea trillada para crear archivos de traducción. Analiza una carpeta src en *.i18n.json archivos *.i18n.json y guarda un .json por idioma que encuentra dentro de los archivos de origen.

Funciona bien, hasta que encuentra más de 16 archivos. Está utilizando through2 para el procesamiento de cada archivo. Ver código fuente a continuación. El método processAll18nFiles() es un conducto personalizado que recibe los archivos de entrada coincidentes, lee el contenido de cada archivo, construye los diccionarios resultantes sobre la marcha y, finalmente, lo entrega al controlador on('finish) para escribir los diccionarios.

Probado en windows y mac. Parece que hay una limitación que impacta mi enfoque, porque funciona bien con 16 archivos o menos.

Todavía buscando, pistas bienvenidas 🙂

Ejemplo de archivo fuente: signs.i18n.json

 { "path": "profile.signs", "data": { "title": { "fr": "mes signes précurseurs", "en": "my warning signs" }, "add": { "fr": "ajouter un nouveau signe", "en": "add a new warning sign" } } } 

Ejemplo de archivo de salida: en.json

 {"profile":{"signs":{"title":"my warning signs","add":"add a new warning sign"}}} 

gulpfile.js

 const fs = require('fs'); const path = require('path'); const gulp = require('gulp'); const watch = require('gulp-watch'); const through = require('through2'); const searchPatternFolder = 'src/app/**/*.i18n.json'; const outputFolder = path.join('src', 'assets', 'i18n'); gulp.task('default', () => { console.log('Ionosphere Gulp tasks'); console.log(' > gulp i18n builds the i18n file.'); console.log(' > gulp i18n:watch watches i18n file and trigger build.'); }); gulp.task('i18n:watch', () => watch(searchPatternFolder, { ignoreInitial: false }, () => gulp.start('i18n'))); gulp.task('i18n', done => processAll18nFiles(done)); function processAll18nFiles(done) { const dictionary = {}; console.log('[i18n] Rebuilding...'); gulp .src(searchPatternFolder) .pipe( through.obj((file, enc, next) => { console.log('doing ', file.path); const i18n = JSON.parse(file.contents.toString('utf8')); composeDictionary(dictionary, i18n.data, i18n.path.split('.')); next(null, file); }) ) .on('finish', () => { const writes = []; Object.keys(dictionary).forEach(langKey => { console.log('lang key ', langKey); writes.push(writeDictionary(langKey, dictionary[langKey])); }); Promise.all(writes) .then(data => done()) .catch(err => console.log('ERROR ', err)); }); } function composeDictionary(dictionary, data, path) { Object.keys(data) .map(key => ({ key, data: data[key] })) .forEach(({ key, data }) => { if (isString(data)) { setDictionaryEntry(dictionary, key, path, data); } else { composeDictionary(dictionary, data, [...path, key]); } }); } function isString(x) { return Object.prototype.toString.call(x) === '[object String]'; } function initDictionaryEntry(key, dictionary) { if (!dictionary[key]) { dictionary[key] = {}; } return dictionary[key]; } function setDictionaryEntry(dictionary, langKey, path, data) { initDictionaryEntry(langKey, dictionary); let subDict = dictionary[langKey]; path.forEach(subKey => { isLastToken = path[path.length - 1] === subKey; if (isLastToken) { subDict[subKey] = data; } else { subDict = initDictionaryEntry(subKey, subDict); } }); } function writeDictionary(lang, data) { return new Promise((resolve, reject) => { fs.writeFile( path.join(outputFolder, lang + '.json'), JSON.stringify(data), 'utf8', err => (err ? reject(err) : resolve()) ); }); } 

Ok, como se explica aquí , uno debe consumir la tubería. Esto se hace agregando un controlador de eventos de “datos” como:

  gulp .src(searchPatternFolder) .pipe( through.obj({ highWaterMark: 4, objectMode: true }, (file, enc, next) => { const { data, path } = JSON.parse(file.contents.toString('utf8')); next(null, { data, path }); }) ) // The next line handles the "consumption" of upstream pipings .on('data', ({ data, path }) => ++count && composeDictionary(dictionary, data, path.split('.'))) .on('end', () => Promise.all(Object.keys(dictionary).map(langKey => writeDictionary(langKey, dictionary[langKey]))) .then(() => { console.log(`[i18n] Done, ${count} files processed, language count: ${Object.keys(dictionary).length}`); done(); }) .catch(err => console.log('ERROR ', err)) );