最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - How to return my CSV data from my service - asyncawait issue? - Stack Overflow

matteradmin7PV0评论

I am attempting to load some CSV data in my API such that I can manipulate it and pass through to my front end, however I am having a few issues returning the data.

I am using fast-csv to do the parsing here.

service.js

const fs = require('fs');
const csv = require('fast-csv');

module.exports.getFileContents = (filepath) => {
    let data = [];

    fs.createReadStream(filepath)
        .pipe(csv.parse({ headers: true }))
        .on('error', error => console.error(error))
        .on('data', row => data.push(row))
        .on('end', () => {
            console.log(data) // This will print the full CSV file fine
            return data;
        });
};

routes.js

router.get('/data/:filename', (req, res) => {
  const file = FS.getFileContents(testUrl + '/' + req.params.filename + '.csv');
  console.log(file); // This prints 'undefined'
  res.send(file);
});

I can print out the CSV contents fine from the service, but I just get 'undefined' from the actual routes. Can somebody please point out what I'm missing?

I am attempting to load some CSV data in my API such that I can manipulate it and pass through to my front end, however I am having a few issues returning the data.

I am using fast-csv to do the parsing here.

service.js

const fs = require('fs');
const csv = require('fast-csv');

module.exports.getFileContents = (filepath) => {
    let data = [];

    fs.createReadStream(filepath)
        .pipe(csv.parse({ headers: true }))
        .on('error', error => console.error(error))
        .on('data', row => data.push(row))
        .on('end', () => {
            console.log(data) // This will print the full CSV file fine
            return data;
        });
};

routes.js

router.get('/data/:filename', (req, res) => {
  const file = FS.getFileContents(testUrl + '/' + req.params.filename + '.csv');
  console.log(file); // This prints 'undefined'
  res.send(file);
});

I can print out the CSV contents fine from the service, but I just get 'undefined' from the actual routes. Can somebody please point out what I'm missing?

Share Improve this question asked Apr 7, 2020 at 20:09 physicsboyphysicsboy 6,39822 gold badges77 silver badges140 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 6

This is a mon problem with JavaScript code, in the following.

.on('end', () => {
    console.log(data);
    return data;
 });

Your on-end handler is an anonymous callback function (because of () =>), so when you return data, you are returning data out of your on-end handler callback function. You are not returning data out of your enclosing getFileContents() function.

Here's a typical way to write this kind of code:

const getFileContents = async (filepath) => {
  const data = [];

  return new Promise(function(resolve, reject) {
    fs.createReadStream(filepath)
      .pipe(csv.parse({ headers: true }))
      .on('error', error => reject(error))
      .on('data', row => data.push(row))
      .on('end', () => {
        console.log(data);
        resolve(data);
      });
  });
}

And then, call it as follows, though this must be within an async function:

const data = await getFileContents('games.csv');

What's happened here is as follows:

  • your getFileContents is now async and returns a promise
  • the CSV data will be available when resolve(data) is executed
  • the caller can await the fulfillment/resolution of this promise to get the data

You could just create a Promise in the service and return it. Once the job is done, resolve it. The returned Promise will wait until it is resolved.

service.js

  const fs = require('fs');
  const csv = require('fast-csv');

   module.exports.getFileContents = (filepath) => {
    let data = [];
    return new Promise((resolve) => {

      fs.createReadStream(filepath)
        .pipe(csv.parse({ headers: true }))
        .on('error', error => console.error(error))
        .on('data', row => data.push(row))
        .on('end', () => {
            resolve(data);
        });
    }
  };

routes.js

router.get('/data/:filename', (req, res) => {
  const file = await FS.getFileContents(testUrl + '/' + req.params.filename + '.csv');
  console.log(file); // This prints only after it is resolved
  res.send(file);
});
Post a comment

comment list (0)

  1. No comments so far