2017-06-02 2 views
1

Ich schrieb eine Funktion, die rekursiv ausgeführt wird, um Dateien zu finden, deren Name die angegebene Welt enthält. Ich verstehe nicht, wie Versprechungen funktionieren und finde keine Möglichkeit, diese Funktion mit Versprechen zu schreiben, obwohl ich mich sehr bemüht habe.Callbacks mit For-Schleife und Rekursion zu Verheißungen konvertieren

Ich versuchte, ein Versprechen innerhalb der Funktion findPath zurückzugeben, aber ich konnte es nicht verwenden, da extractFiles Aufrufe findPath. Ich habe versucht, eine Liste von Versprechungen zu erstellen und alle zurückzuschicken, aber auch keinen Erfolg.

Also wie könnte ich diese Funktionen mit Versprechen schreiben?

const fs = require('fs'); 
const path = require('path'); 


function findPath(targetPath, targetWord, done) { 
    if (!fs.existsSync(targetPath)) return; 

    fs.readdir(targetPath, (err, allPaths) => { 
    if (err) done(err, null); 

    for (aPath of allPaths) { 
     aPath = path.join(targetPath, aPath); 
     extractFiles(aPath, targetWord, done); 
    } 
    }); 

    function extractFiles(aPath, targetWord, done) { 
    fs.lstat(aPath, (err, stat) => { 
     if (err) done(err, null); 

     if (stat.isDirectory()) { 
     findPath(aPath, targetWord, done); 
     } 
     else if (aPath.indexOf(targetWord) >= 0) { 
     let fileName = aPath.split('.')[0]; 
     done(null, fileName); 
     } 
    }); 
    } 
} 

findPath('../modules', 'routes', file => { 
    console.log(file); 
}); 
+0

schreiben Sie dies für die Praxis oder weil Sie es brauchen? –

+0

scheint "fertig" könnte mehr als einmal zurückgerufen werden? Ist das korrekt? –

+0

@DayanMorenoLeon für die Praxis funktioniert die Funktion gut mit Rückrufen. Ich versuche es zu konvertieren, um Versprechungen zu bekommen. Ich beobachte die meisten Vorträge bei youtube, aber sie alle geben einfache Beispiele. –

Antwort

0

Zum einen des "Kern" Code besser lesbar zu machen, ich

const promisify1p = fn => p1 => new Promise((resolve, reject) => { 
    fn(p1, (err, result) => { 
     if(err) { 
      reject(err); 
     } else { 
      resolve(result); 
     } 
    }); 
}); 
const readdirAsync = promisify1p(fs.readdir); 
const lstatAsync = promisify1p(fs.lstat); 

dann die fs-Funktionen promisify würde, die Kette nur die Versprechungen wie bei allen anderen Versprechungen

const fs = require('fs'); 
const path = require('path'); 

function findPath(targetPath, targetWord) { 
    const readPath = target => 
     readdirAsync(target) 
     .then(allPaths => 
      Promise.all(allPaths.map(aPath => extractFiles(path.join(target, aPath)))) 
      .then(x => x.filter(x=>x)) // remove all the "false" entries - i.e. that don't match targetWord 
      .then(x => [].concat.apply([], x)) // flatten the result 
     ); 
    const extractFiles = aPath => 
     lstatAsync(aPath).then(stat => { 
      if (stat.isDirectory()) { 
       return readPath(aPath); 
      } else if (aPath.includes(targetWord)) { 
       return aPath.split('.')[0]; 
      } 
      return false; 
     }); 
    return readPath(targetPath); 
} 

findPath('../modules', 'routes') 
.then(results => { 
    // do things with the results - which is an array of files that contain the targetWord 
}) 
.catch(err => console.error(err)); 

Nicht viel dabei.

+0

Nochmals vielen Dank. Ich wusste nicht, wie ich Kernfunktionalität promi- vieren sollte. Hat Promisting irgendwelche Nebenwirkungen? –

+0

in diesem Fall nein - ich kann nicht für alle Fälle sprechen: p bluebird verspricht hat promisifaction gebaut, die wahrscheinlich viel robuster als der Code ist, den ich hier vorgestellt habe - Anmerkung: Sie brauchen ** nicht ** das zu tun So, ich finde nur, dass Verschieben * Callback * Code weg von * Versprechen * Code macht es viel einfacher zu lesen: p –

+0

Ich finde heraus, dass Knoten 8 hat eine Funktion zur Promisifiying: [util.promisify()] (http: // 2ality.com/2017/05/util-promisify.html) –