1

I have the following code :

var fs = require("fs");

function getMediaList(){
    var media_copy_list, line_list;
    media_copy_list = [];

    fs.readFile("input.csv", function(err, data) {

      line_list = data.toString('utf-8').trim().split('\n');
      return line_list.forEach(function(file_line) {
        var output_path, source_path, split_list;
        if (file_line.length) {
          split_list = file_line.split(';');
          console.log(split_list[0]);
          if (split_list.length >= 2) {
            source_path = split_list[0].toString('utf-8').trim();
            output_path = split_list[1].toString('utf-8').trim();
            media_copy_list.push({
              source: source_path,
              destination: output_path
            });
          }
        }
      });
    });
}

You can see that that I'm filling a list with :

media_copy_list.push({
  source: source_path,
  destination: output_path
});

What I'd like to do is to return this list once I have finished reading the input.csv file.

I don't have any issues if I read the file synchrnously( just have to call return media_copy_list). But in this case , I don't know.

I heard about async.parallel but really don't know how to apply.

Example of input.csv :

FirstPart;SecondPart

Test/test2;Whatever/example

4
  • Return the result to where? Commented Dec 21, 2015 at 14:10
  • Ah sorry, actually the code is in a function. So the function should return it Commented Dec 21, 2015 at 14:11
  • Please edit the question and include all the relevant information. Commented Dec 21, 2015 at 14:13
  • 2
    Possible duplicate of How do I return the response from an asynchronous call? Commented Dec 21, 2015 at 14:21

3 Answers 3

1

Just wrap your code inside a promise and resolve it only once you're done. Some suggest callbacks, which does pretty much the same thing, but this pattern is discouraged, now. You should really use a promise.

var fs = require("fs");

function getMediaList(file){
  return new Promise(function (resolve, reject) {
    fs.readFile(file, 'utf-8', function(err, data) {
      if (err) {
        return reject(err);
      }

      resolve(data.split('\n').reduce(function(media_copy_list, file_line) {
        var output_path;
        var source_path;
        var split_list;

        file_line = file_line.trim();

        if (file_line.length) {
          split_list = file_line.split(';');
          console.log(split_list[0]);

          if (split_list.length >= 2) {
            source_path = split_list[0].toString('utf-8').trim();
            output_path = split_list[1].toString('utf-8').trim();
            media_copy_list.push({
              source: source_path,
              destination: output_path
            });
          }
        }

        return media_copy_list;
      }, []));
    });
  });
}

Then, invoke with

getMediaList('input.csv').then(function (mediaList) {
  // ...
}).catch(function (err) {
  console.error(err.stack);
});

Note: bluebird, Q, etc. are quite unnecessary since Node 4.2+. Unless you are using an earlier version of Node, try to avoid them. IMO.

The reason why Promises are encouraged is because Node will implement async/await, which will allow you to call this exact same function like :

var mediaList = await getMediaList('input.csv');
Sign up to request clarification or add additional context in comments.

Comments

1

As noted in the comments, you don't want to return the list from the function.. what you should do is include a callback as a parameter to getMediaList and call that callback with your results. I would use async.each for looping through the lines in the file. You can read more about async.each here: https://github.com/caolan/async#each. Here is an example:

var fs = require("fs");

function getMediaList(callback){
    var media_copy_list, line_list;
    media_copy_list = [];

    fs.readFile("input.csv", function(err, data) {
      if(err) {
        return callback(err);
      }
      line_list = data.toString('utf-8').trim().split('\n');
      async.each(line_list, function(file_line, next) {
        var output_path, source_path, split_list;
        if (file_line.length) {
          split_list = file_line.split(';');
          console.log(split_list[0]);
          if (split_list.length >= 2) {
            source_path = split_list[0].toString('utf-8').trim();
            output_path = split_list[1].toString('utf-8').trim();
            media_copy_list.push({
              source: source_path,
              destination: output_path
            });
          }
        }
        next(err); 
      }, function (err) {
        callback(err, media_copy_list);
      }
    });
}

Comments

0

Or you can use promises(bluebird in the case below).

var Promise  = require('bluebird'),
fs = require("fs"),
media_copy_list, line_list,
media_copy_list = [];

fs.readFile("input.csv", function(err, data) {
 line_list = data.toString('utf-8').trim().split('\n');
  Promise.map(line_list, function(file_line) {
    var output_path, source_path, split_list;
    if (file_line.length) {
      split_list = file_line.split(';');
      if (split_list.length >= 2) {
        source_path = split_list[0].toString('utf-8').trim();
        output_path = split_list[1].toString('utf-8').trim();
        media_copy_list = {
          source: source_path,
          destination: output_path
        };
      }
    }
    return media_copy_list 
 }).then(function(values){
    console.log(values);
 })

});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.