Gigi
Gigi

Reputation: 340

node js - getting results from a callback

Here is my node js code:

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 );
    }
}

After calling GetFilesList() function, ResponseData.str does not contain the file names although I see them in the concole.

Based on answers got here, I modified the functions as following:

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" );
                 } )
}

The "then" part is not executed. Strange enough, if a I place a second request to server (i.e. a simply page refresh in browser) I see just then that ResponseData.str has the file names I expect (but not the "x"es).

Upvotes: 1

Views: 177

Answers (3)

Ralph
Ralph

Reputation: 1668

Let's start with the idea that you are using asynchronous calls wrong.

First of all, it is a very bad idea to write functions that use data externally, especially when asynchronous is involved (let alone function handlers).

Please brush on your async coding knowledge. You should start by having your functions only work with passed in variables, nothing from outside (no side effects). While your small example might work eventually, you can not build a good code base going forward like this.

Second, as others pointed out, you are probably calling GetFilesList and then printing the result. So your call to GetFilesList starts an asynchronous operation and then the function ends (in that it exists). But this doesn't mean it finished what it intended to do, so in the next line you are printing ResponseData and get the surprise that it is empty. After you print it, the disk operation would be done and then your callback is called and at that point your data is filled out, your question should be "when to know" or "how to wait" until it gets filled. You are mixing synchronous logic with async logic, which is totally okay and it happens to everyone at first.

You don't need promises to fix this problem, promises is the preferred way, but if you are just starting async coding, I personally would recommend callbacks until you understand it 100% and then move over to promises.

Have a look at this code, I added main to try to help you understand the flow.

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);
  }
});

Upvotes: 0

Eric Yang
Eric Yang

Reputation: 2750

Depending on when you're accessing ResponseData, it's possible that you're printing it out before the callback finishes.

To prevent yourself from getting into callback hell and the asynchronous nature of node.js, use promises

a common pattern is the following:

new Promise((resolve, reject) => fs.readdir(foldername, (err, files) => {
    resolve(files)
}).then((files) => {
     //do something with the files
})

Upvotes: 0

CFrei
CFrei

Reputation: 3627

ResponseData.str DOES contain the files, but you need to keep going with your code inside the callback after the for-loop.

Upvotes: 1

Related Questions