0

When using await on a function with callback, such as fs.writeFile, await doesn't wait for the code inside the callback to execute. For example:

const fs = require("fs")
async function test() {
    for (let i = 0; i < 3; i++) {
        console.log(`processing ${i}`)
        const fileName = `${i}.json`
        await fs.writeFile(fileName, JSON.stringify(i), err => {
            if (err) throw err
            console.log(`file ${i} is written`)
        })
        console.log(`${i} is done.`)
    }
}

test()

The above code produces:

processing 0
0 is done.
processing 1
1 is done.
processing 2
2 is done.
file 1 is written
file 0 is written
file 2 is written

instead of:

processing 0
file 0 is written
0 is done.
processing 1
file 1 is written
1 is done.
processing 2
file 2 is written
2 is done.

Could anyone please explain why await fails to let it finish writing the file before continuing?

  • 4
    Because `writeFile` does not work with promises. – deceze Dec 18 '21 at 15:08
  • 2
    await works with promises however here fs.writeFile isnt a promise. https://stackoverflow.com/questions/31978347/fs-writefile-in-a-promise-asynchronous-synchronous-stuff – N.K. Dec 18 '21 at 15:09
  • 3
    You can't `await` the _standard_ `writeFile` - it doesn't return a promise. But! You _can_ [use the new promisified version of `writeFile`](https://nodejs.org/api/fs.html#fspromiseswritefilefile-data-options). Just make sure your version of Node is up-to-date. – Andy Dec 18 '21 at 15:10
  • 1
    `await` doesn't magically know about the callback. It only waits for the promise that is its operand. – Bergi Dec 18 '21 at 18:20

1 Answers1

1

This is because writeFile doesn't return a Promise and await waits for a Promise resolution before suspending the execution. You can either upgrade to the latest version of writeFile or write a function which returns a promise :

const fs = require("fs")
async function test() {
    for (let i = 0; i < 3; i++) {
        console.log(`processing ${i}`)
        const fileName = `${i}.json`
        await writeToFile(fileName, i);
        console.log(`${i} is done.`)
    }
}

function writeToFile(fileName, index) {
  return new Promise((resolve, reject) => {
     fs.writeFile(fileName, JSON.stringify(index), err => {
            if (err) {
              // denotes failure
              reject(err)
            }
            console.log(`file ${index} is written`);
            // denotes success
            resolve(true)
     })
  });
}

test()
Kanishk Anand
  • 1,686
  • 1
  • 7
  • 16