2017-06-27 1 views
1

Ich erstelle eine Funktion in node.js, die die Dateien eines Verzeichnisses durchläuft. Es soll den Dateinamen der returnData -Variable hinzufügen und dann returnData zurückgeben. Es gibt jedoch nichts zurück. Ich habe ein paar console.log-Anweisungen in die Funktion geschrieben, um mir beim Debuggen zu helfen, aber ich kann nicht herausfinden, warum es nicht funktioniert.Datei-Loop-Funktion

function loopMusic (directory) { 
    var returnData = ""; 
    fs.readdir (directory, function (err, files) { 

     if (err) { 
      console.log (err); 
     } 

     files.forEach (function (file, index) { 
      returnData += file; 
      console.log (returnData); 
     }); 
    }); 
    console.log (returnData); 
    return returnData; 
} 

Die erste console.log Anweisung ist in der Lage, die Dateien zu drucken, aber das man direkt vor der Rückkehr druckt nur eine neue Zeile.

+2

Sie müssen etwas über asynchronen Code und wie Callbacks arbeiten. – gforce301

+1

'fs.readdir' ist asynchron, daher wird es später aufgerufen, dann wird die Methode zurückgegeben. Die Dateisystembibliothek in nodejs erlaubt synchrone Aufrufe, die als "readdirSync" bezeichnet werden und ein Array von Strings zurückgibt. –

+0

Mögliches Duplikat von [Wie gebe ich die Antwort von einem asynchronen Anruf zurück?] (Https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-a-asynchronous-call) – gforce301

Antwort

2

Sie die Funktion ein Versprechen zurückkehren machen:

function loopMusic (directory) { 
    return new Promise((resolve, reject) => { 
     fs.readdir (directory, function (err, files) { 

      if (err) { 
      reject(err); 
      return; 
      } 

      files.forEach (function (file, index) { 
       returnData += file; 
       console.log (returnData); 
      }); 

      resolve(returnData); 
    }); 
} 

Sie auf diese Weise verwenden würde:

loopMusic('...') 
    .then((data) => console.log(data)) 
    .catch((err) => ...); 
+0

Das stimmt! Ich werde es reparieren. Vielen Dank! –

0

fs.readdir ist asynchron, es bedeutet nicht zurück mit dem Ergebnis, wenn man es so nennen . Stattdessen wird das Ergebnis dem Rückruf bereitgestellt, der aufgerufen wird, wenn der Befehl die Verarbeitung beendet. Es ruft die Funktion zurück, die Sie angegeben haben (daher der Name).

Wenn Sie dies synchron tun wollten können Sie folgendes tun:

function loopMusic (directory) { 
    var returnData = ""; 
    var files = fs.readdirSync(directory); 
    files.forEach (function (file, index) { 
     returnData += file; 
     console.log (returnData); 
    }); 
    console.log(files); 
    return returnData; 
} 

, dass eine Reihe von mushed zusammen Pfaden Datei, wie in Ihrer Frage zurückkommen würde.

Blockieren ist jedoch normalerweise keine gute Idee und Sie sollten die asynchrone Version verwenden. Ich möchte in diesen Situationen eine Promise zurückgeben. Hier ist ein Beispiel, das ein Versprechen mit dieser Zeichenfolge zurückgibt. Dies ist technisch nicht notwendig, da der Callback einfach verwendet werden könnte ... aber lassen Sie uns einfach so tun.

function loopMusic (directory) { 
    return new Promise(function(resolve, reject) { 
     fs.readdir (directory, function (err, files) { 
      if (err) { 
       return reject(err); 
      } 

      let returnData = ""; 
      files.forEach (function (file, index) { 
       returnData += file; 
      }); 

      resolve(returnData);   
     }); 
    }); 
} 

Verbrauch:

var musicPromise = loopMusic(dir); 
musicPromise.then((musicStr) => console.log(musicStr)), (err) => console.log(err)); 

Die asynchrone Natur dieser es ein bisschen schwer zu folgen, macht da Dinge, um nicht passieren, aber wenn Promises mit der then() verwendet wird, zu handhaben, was passiert, Erfolg (oder Misserfolg), wenn es später vervollständigt wird. Wenn Sie ES2017 + (die neueste Version von Node) verwenden, können Sie das Muster async/await verwenden. Denken Sie daran, mein Versprechen Beispiel oben:

async function loopMusicAsync(directory) { 
    try{ 
     return await loopMusic(directory); //promise returned 
    } 
    catch(error) { 
     console.log(error); //promise rejected 
     return null; 
    } 
}