Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async function returns Promise { <pending> }?

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).

like image 498
Jake Wilson Avatar asked May 16 '17 23:05

Jake Wilson


People also ask

Do async functions return a promise?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

Does async await always return promise?

The word “async” before a function means one simple thing: a function always returns a promise. Other values are wrapped in a resolved promise automatically. So, async ensures that the function returns a promise, and wraps non-promises in it.

When a promise object is in the pending state the result is?

The Promise object supports two properties: state and result. While a Promise object is "pending" (working), the result is undefined. When a Promise object is "fulfilled", the result is a value. When a Promise object is "rejected", the result is an error object.

Does await wait for all promises?

If a Promise is passed to an await expression, it waits for the Promise to be fulfilled and returns the fulfilled value.


1 Answers

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.
  }
}
like image 88
Mark McKelvy Avatar answered Oct 05 '22 08:10

Mark McKelvy