2017-02-27 3 views
0

Ich habe einen Code unten, der alle Dateien in einem Verzeichnis mit bestimmten Schlüsseln und Werten zurückgibt. Einer dieser Schlüssel, die ich sein möchte, ist Directory mit einem booleschen Wert.Knoten Promise Rückgabeobjekt mit Wert der aufgelösten Versprechen

Der folgende Code funktioniert gut, aber ich fragte mich, ob es eine Möglichkeit gab, die Promise.all/iterating über Versprechen zu entfernen und stattdessen den aufgelösten Wert der stat.isDirectory() auf meine Dateien Objekte direkt in meiner Karte.

Meine Lösung Ich habe versucht, aber nicht:

Ich habe versucht, so etwas wie dieses:

isDirectory: fs.statAsync(path).then((stat) => stat.isDirectory()) 

Und dann tun ein Promise.all auf den alle isDirectory Tasten

Arbeits Code:

const Promise = require('bluebird'), 
    os = require('os'), 
    _ = require('lodash'), 
    fs = Promise.promisifyAll(require('fs')), 
    desktopPath = `${os.homedir()}/Desktop`; 

let files = []; 

return fs.readdirAsync(desktopPath) 
    .then((filesName) => files = _.map(filesName, (fileName) => ({ 
     path: `${desktopPath}/${fileName}`, 
     name: fileName, 
     ext: _.last(fileName.split('.')) 
    }))) 
    .then(() => Promise.all(_.map(files, (file) => fs.statAsync(file.path)))) 
    .then((stats) => _.forEach(stats, (stat, idx) => { 
     files[idx].isDirectory = stat.isDirectory(); 
    })) 
    .then(() => { 
     console.log(files); 
    }) 

Gibt es trotzdem den Promise.all und _.forEach Teil am Ende zu entfernen? Und machen Sie stattdessen diese Aktionen in meiner Karte?

Antwort

0

Angenommen, Sie den aktuellen Knoten verwenden - Sie können async/await, setzte async vor Ihrer Funktionsdefinition und zu tun:

const fileNames = await fs.readdirAsync(desktopPath); 
const files = await Promise.map(fileNames, fileName => Promise.props({ 
    path: `${desktopPath}/${fileName}`, 
    name: fileName, 
    ext: fileName.split('.').pop(), 
    isDirectory: fs.statAsync(`${desktopPath}/${fileName}`); 
}))); 
console.log(files); 
return files; 
1

Sie können nicht die Promise.all vollständig entfernen, weil Sie für alle Dateien warten sollen, bis zum Ende bevor Sie das Endergebnis verwenden. Aber Sie können alles in einem Anruf tun.

Da map synchron ist, wird nicht auf das Ende der fs.statAsync gewartet. Aber Sie können ein Array von Versprechungen von fs.statAsync erstellen, die mit dem endgültigen Dateiobjekt auflösen und die einfach darauf warten, dass alle mit Promise.all abgeschlossen werden.

Eine ausführliche Version mit einigen Kommentaren zur Klarstellung:

fs.readdirAsync(desktopPath) 
    .then(fileNames => { 
    // Array of promises for fs.statAsync 
    const statPromises = fileNames.map(fileName => { 
     const path = `${desktopPath}/${fileName}`; 
     // Return the final file objects in the promise 
     return fs.statAsync(path).then(stat => ({ 
     path, 
     name: fileName, 
     ext: _.last(fileName.split(".")), 
     isDirectory: stat.isDirectory() 
     })); 
    }); 
    // Promise.all to wait for all files to finish 
    return Promise.all(statPromises); 
    }) 
    .then(finalFiles => console.log(finalFiles)); 

und die kompakte Version:

fs.readdirAsync(desktopPath) 
    .then(fileNames => Promise.all(
    fileNames.map(fileName => 
     fs.statAsync(`${desktopPath}/${fileName}`).then(stat => ({ 
     path: `${desktopPath}/${fileName}`, 
     name: fileName, 
     ext: _.last(fileName.split(".")), 
     isDirectory: stat.isDirectory() 
     }))) 
)) 
    .then(finalFiles => console.log(finalFiles)); 
Verwandte Themen