annieg4123
annieg4123

Reputation: 69

async/await not working properly with fs.writeFile

I pass a callback to fs.writeStream, and for some reason any tasks after it are being called first, before the callback is executed.


async function writeFile(file, callBack) {
    // awaiting this also doesn't work
  fs.writeFile(arg1, arg2, arg3, (error) => callBack(error)) 

}

async function task() {
  let count = 0;

  const callBack = (error) => {
    if (error) {
      count--;
    } else {
      count++;
    }
  }

  for(const file of files) { // files.length = 1
    await writeFile(file, callBack);  
  }
  
  console.log(count) // Prints 0, should be 1. Why does this get called before the callback?
}

Upvotes: 0

Views: 5341

Answers (2)

derpirscher
derpirscher

Reputation: 17407

First of all, you are calling it wrong. If you want to wait for an async function you have to call it like this with await

await yourFunction(...);

and not like this with async

async yourFunction();

Second, you are obviously mixing async functions and functions with callbacks. Ie, when you have

async function yourFunction() {
  anotherFunction((error, data) => { 
     ... 
  });
}

you are actually returning a Promise<void> which immediately resolves. async function do not wait for any callbacks of callback-based functions.

And third, you are not using the file parameter of your writeFile(file, callBack) function, but three completely undefined arguments arg1, arg2, arg3

For your current problem, there are two possibilities

  1. You import the promise functions of the fs module and use them properly (available since Node v10)

     const fsp = require("fs").promises;
    
     async function writeFile(filename, data, errorHandler) {
       try{
         await fsp.writeFile(filename, data);
       } catch (e) {
         errorHandler(e);
       }
     }
    
  2. You import the classic callback-form of the fs module and wrap the functions into a promise

     const fs = require("fs");
    
     async function writeFile(filename, data, errorHandler) {
       return new Promise((resolve, reject) => {
         fs.writeFile(filename, data, (e) => {
           if (e) {
             errorHandler(e);
             // if you want to continue and adjust the count 
             // even if the writeFile failed
             // you don't need the reject here
             return reject(e);
           }
           resolve();
         });
       });
     }
    

Upvotes: 2

kernel
kernel

Reputation: 3743

Given you imported the correct fs library, namely fs/promises, your answer should look like this:

async function writeFile(file) {
  await fs.writeFile(file);
}

async function task() {
  let count = 0;

  const callBack = (error) => {
    if (error) {
      count--;
    } else {
      count++;
    }
  }

  for(const file of files) { // files.length = 1
    await writeFile(file);  
  }
  
  console.log(count) // Prints 0, should be 1. Why does this get called before the callback?
}

You were missing the required await to actually await the asynchronous result of fsPromises.writeFile as you can see here: https://nodejs.org/dist/latest-v15.x/docs/api/fs.html#fs_fspromises_writefile_file_data_options Also if you're using the promise based fs you will not have nor need the callback (ftfy)

If you still want to count, do it like this:

async function writeFile(file) {
  await fs.writeFile(file);
}

async function task() {
  let count = 0;

  for (const file of files) { // files.length = 1
    try {
      await writeFile(file);
      count++; // <-------- NOTICE THIS PART HERE
    } catch (e) {
      count--;
    }
  }
  
  console.log(count) // Prints 0, should be 1. Why does this get called before the callback?
}

Upvotes: 0

Related Questions