async function returns Promise { <pending> }?

12,430

All async functions return a promise as was mentioned in the comments. You could therefore re-write your readFile function like this:

function readFile() {
  return new Promise((resolve, reject) => {
    fs.readFile('./file.txt', function (err, content) {
      if (err) {
        return reject(err)
      }
      resolve(content)
    })
  })
}

You would then consume the return value of readFile via await:

console.log(await readFile()) // will log your actual file contents.

The usual workflow with this paradigm is to break your async operations into separate functions that each return a promise, and then run them all inside a broader async function, much like you suggest, but with awaits and some error handling like so:

async function doSomething () {
  try {  
    const fileCheck = await fileExists(path)

    if (fileCheck) {
      const buffer = await readFile(path)
      await updateDatabase(buffer)
      // Whatever else you want to do
    }
  } catch (err) {
    // handle any rejected Promises here.
  }
}
Share:
12,430
Jake Wilson
Author by

Jake Wilson

Experienced in developing tools for 3D animation, motion capture, video game and movie production, web development, Android development, responsive design, etc...

Updated on June 16, 2022

Comments

  • Jake Wilson
    Jake Wilson almost 2 years

    I have the following async function:

    async function readFile () {
      let content = await new Promise((resolve, reject) => {
        fs.readFile('./file.txt', function (err, content) {
          if (err) {
            return reject(err)
          }
          resolve(content)
        })
      })
    
      console.log(content)
    }
    
    readFile()
    

    This runs just fine. It outputs the file buffer to the console as expected. But now, if I try to instead return the value:

    async function readFile () {
      let content = await new Promise((resolve, reject) => {
        fs.readFile('./file.txt', function (err, content) {
          if (err) {
            return reject(err)
          }
          resolve(content)
        })
      })
    
      return content
    }
    
    console.log(readFile())
    

    I now get:

    Promise { <pending> }
    

    Why is this? Why can you use a value inside that function but when you return it out of the function it's now a Promise?

    How do you actually make use of this in a normal workflow? For example, lets say I wanted to check if a file exists, then read in the file, then update some database with the content, the synchronous pseudo code would look something like this:

    if (fileExists(path)) {
      buffer = readFile(path)
      updateDatabase(buffer)
    }
    

    That workflow consists of 3 individual async operations. How would you do something like this with async/await? Is the key that you have to have your entire script wrapped in an async function?

    async function doSomething () {
      if (fileExists(path)) {
        buffer = readFile(path)
        updateDatabase(buffer)
      }
    }
    

    (Keep in mind that is just pseudo-code but hopefully its gets my point across).