ASYNC / AWAIT SyntaxError: await is only valid in async functions and the top level bodies of modules

Viewed 16165

I am doing some really simple testing regarding reading csv files into a json format using the csvtojson node module, I used the code below as a template

a,b,c
1,2,3
4,5,6
*/
const csvFilePath='<path to csv file>'
const csv=require('csvtojson')
csv()
.fromFile(csvFilePath)
.then((jsonObj)=>{
    console.log(jsonObj);
    /**
     * [
     *  {a:"1", b:"2", c:"3"},
     *  {a:"4", b:"5". c:"6"}
     * ]
     */ 
})
 
// Async / await usage
const jsonArray=await csv().fromFile(csvFilePath);

I am mostly focusing on the

// Async / await usage

const jsonArray=await csv().fromFile(csvFilePath);

Section of the code. Right so here is my code

// const JSONtoCSV = require("json2csv")
// const FileSystem = require("fs")

async function test()
{
    const data = await CSVtoJSON().fromFile('./input.csv')
    return data
}

let temp = await test()

console.log(temp)

and ever which way I have tried it I always get the following error

let temp = await test()
           ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)
    at node:internal/main/run_main_module:17:47

or

const data = await CSVtoJSON().fromFile('./input.csv');
             ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)
    at node:internal/main/run_main_module:17:47

if I switch the code to be all top level like so

const CSVtoJSON = require("csvtojson")
// const JSONtoCSV = require("json2csv")
// const FileSystem = require("fs")

const data = await CSVtoJSON().fromFile('./input.csv')

console.log(data)

I can't see why this isn't working.

EDIT: I made the change as @tasobu noted. Now all I get is a returned promise

const data = (async () => {
    return await CSVtoJSON().fromFile('./input.csv')
})

console.log(data)
Debugger attached.
Promise { <pending> }
Waiting for the debugger to disconnect...
5 Answers

You can use an IIFE here (Read more about it here)

(async function main () {
    // You can use await inside this function block
})();

A Promise return something in the future so you need a way to wait for it.

// const CSVtoJSON = require("json2csv")
// const FileSystem = require("fs")
let temp = undefined;

async function test()
{
    const data = await CSVtoJSON().fromFile('./input.csv')
    // do your stuff with data
    
    temp = data;

    console.log(temp) // at this point you have something in.
    return true
}

test();
console.log(temp) // at this point nothing was there.

Put your whole code into an async function and call it, so you won't have any thing other than some const statements and function/class declarations outside of the function:

async function main () {
  // All code here, can use await
}

main().then(() => process.exit(0), e => { console.error(e); process.exit(1) })

Other solutions:

  • Add "type": "module" into package.json, and replace all const x = require('x') with import x from 'x'. If you don't/can't have package.json (e.g. a script in /usr/bin/), then change file's extension from .js to .mjs. By the way: node script.mjs works, node script doesn't (it says "Cannot find 'script'"). Tested with Node.js 16.15.0 LTS and 18.2.0.
  • Or use TypeScript.

You have to just leave out the await section, if you don't want to use it.

const csvFilePath = "./data.csv"
const csv = require("csvtojson")
csv()
  .fromFile(csvFilePath)
  .then((jsonObj) => {
    console.log(jsonObj)
  })

// Async / await usage
//const jsonArray = await csv().fromFile(csvFilePath)

Or:

// Async / await usage
async function csvToJson() {
  const res = await csv().fromFile(csvFilePath)
  console.log(res)
}

csvToJson()
Related