How to return Papa-parsed CSV via promise/async-await
Asked Answered
M

1

5

Can someone help me understand why this returns a pending promise, rather than the data?

async function toJson (filepath) {
  const file = fs.createReadStream(filepath)
  let json = new Promise((resolve, reject) => {
    Papa.parse(file, {
      header: true,
      complete (results, file) {
        resolve(results)
      },
      error (err, file) {
        reject(err)
      }
    })
  })
  let result = await json
  return result.data
}

If I change the return result.data line to console.log(result.data), it logs the data array to the console, as expected. Why won't it simply return that array?!?!

Methoxychlor answered 3/6, 2019 at 12:3 Comment(1)
An asyncFunction is guaranteed to return Promise. It should be no surprise that toJson() does so. The problem you are having is caused by not awaiting the result in the caller. Alternatively you could use .then(). Avoid mixing the two within a single function.Moncear
J
18

As Roamer-1888 added in the comments, async functions always return a Promise, even if you await inside it and then return the data it will return as a Promise.

In the function's caller, you will have to await the Promise or use .then() on it in order to access the delivered data.

The toJson function could be better written to just return a Promise like this

function toJson (filepath) {
  const file = fs.createReadStream(filepath)
  return new Promise((resolve, reject) => {
    Papa.parse(file, {
      header: true,
      complete (results, file) {
        resolve(results.data)
      },
      error (err, file) {
        reject(err)
      }
    })
  })
}

Now when you call toJson(), you can use either await if you are inside of an async function or chain .then() on the returned Promise to access the data.

async function main() {
  try {
    const data = await toJson(filepath)
    // do something with the data...
  } catch (err) {
    console.error('Could not parse json', err)
  }
}

Or with .then()

toJson('path')
.then(console.log)
.catch(console.log)

You will be able to catch errors from the underlaying FileReader (thanks to calling reject inside the error function). Keep in mind that by calling resolve with results.data you put aside results.errors and results.meta which contain useful information about the read csv.

Jehias answered 3/6, 2019 at 12:19 Comment(2)
It's the same way we add a promise in vanilla javascript! thank you!Denitadenitrate
Thank you for this solution! I was struggling and realized it was because I didn't explicitly make Papa.parse a new Promise. Awesome!Kilbride

© 2022 - 2024 — McMap. All rights reserved.