Voici mon code node js:

var ResponseData = { str: "" };

function GetFilesList( FolderName, ResponseData )
{
    fs.readdir( FolderName, GetFilesList_callback );
}

function GetFilesList_callback( Err, Files )
{   
    if( Err ) throw Err;
    for( var Idx in Files )
    {
        var Entry = "File " + Idx + " =" + Files[ Idx ] + "=";
        ResponseData.str += Entry;
        console.log( Entry );
    }
}

Après avoir appelé la fonction GetFilesList (), ResponseData.str ne contient pas les noms de fichiers bien que je les vois dans la concole.

Sur la base des réponses obtenues ici, j'ai modifié les fonctions comme suit:

function GetFilesList( FolderName, ResponseData )
{
    var prom = new Promise( function( resolve, reject )
             { fs.readdir( FolderName, GetFilesList_callback ) } );
    prom.then( function( Files )
                 {
                    ResponseData.str += "x";
                    console.log( "after_promise" );
                 } )
}

La partie "alors" n'est pas exécutée. Assez étrange, si je place une deuxième demande au serveur (c'est-à-dire une simple actualisation de page dans le navigateur), je vois juste que ResponseData.str a les noms de fichiers que j'attends (mais pas les "x" es).

1
Gigi 13 avril 2018 à 22:07

3 réponses

Meilleure réponse

Commençons par l'idée que vous utilisez mal les appels asynchrones.

Tout d'abord, c'est une très mauvaise idée d'écrire des fonctions qui utilisent des données en externe, en particulier lorsque asynchrone est impliqué (sans parler des gestionnaires de fonctions).

Veuillez brosser vos connaissances en codage asynchrone. Vous devriez commencer par faire fonctionner vos fonctions uniquement avec des variables passées, rien de l'extérieur (pas d'effets secondaires). Bien que votre petit exemple puisse éventuellement fonctionner, vous ne pouvez pas construire une bonne base de code à l'avenir comme ceci.

Deuxièmement, comme d'autres l'ont souligné, vous appelez probablement GetFilesList puis imprimez le résultat. Votre appel à GetFilesList démarre donc une opération asynchrone, puis la fonction se termine (en ce sens qu'elle existe). Mais cela ne signifie pas qu'il a terminé ce qu'il avait l'intention de faire, donc dans la ligne suivante, vous imprimez ResponseData et obtenez la surprise qu'il soit vide. Après l'avoir imprimée, l'opération sur le disque serait effectuée, puis votre rappel est appelé et à ce moment-là, vos données sont remplies, votre question devrait être "quand savoir" ou "comment attendre" jusqu'à ce qu'il soit rempli. Vous mélangez la logique synchrone avec la logique asynchrone, ce qui est tout à fait correct et cela arrive à tout le monde au début.

Vous n'avez pas besoin de promesses pour résoudre ce problème, les promesses sont le moyen préféré, mais si vous commencez simplement le codage asynchrone, je recommanderais personnellement des rappels jusqu'à ce que vous le compreniez à 100%, puis passez aux promesses.

Jetez un oeil à ce code, j'ai ajouté main pour essayer de vous aider à comprendre le flux.

const fs = require("fs");

function getFilesList(FolderName, callback) {
  fs.readdir(FolderName, callback);
}

function main(callback) {
  getFilesList(".", function(err, files) {
    if(err) {
      return callback(err);
    }

    const responseData = {str: ""};

    for(const Idx in files) {
      const Entry = "File " + Idx + " =" + files[Idx] + "=";
      responseData.str += Entry;
      console.log(Entry);
    }

    callback(null, responseData);
  });
}

main(function(err, responseData) {
  if(err) {
    console.log("Error:", err);
  } else {
    console.log(responseData);
  }
});
0
Ralph 20 avril 2018 à 13:38

Selon le moment où vous accédez à ResponseData, il est possible que vous l'imprimiez avant la fin du rappel.

Pour vous empêcher d'entrer dans l'enfer de rappel et la nature asynchrone de node.js, utilisez des promesses

Un schéma courant est le suivant:

new Promise((resolve, reject) => fs.readdir(foldername, (err, files) => {
    resolve(files)
}).then((files) => {
     //do something with the files
})
0
Eric Yang 13 avril 2018 à 19:16

ResponseData.str contient les fichiers, mais vous devez continuer avec votre code dans le rappel après la boucle for.

1
CFrei 13 avril 2018 à 19:13