Home > Mobile >  Asynchronous tasks and await calls
Asynchronous tasks and await calls

Time:12-15

So I've been thinking about something lately and can't come up with any answer to this by myself. Imagine we define a function that resolves a promise and we call it multiple times through the code using await. Is the promise actually called multiple times or is it called only once and its value is used multiple times (where we await the function) ?

To set an example :

function readFile(file) {
  //the function returns a promise with value from FileReader.readAsText()
}
let toto = (await readFile("somefile")).concat(" / ", "toto")
let titi= (await readFile("somefile")).concat(" / ", "titi")

Is readFile() actually reading the file twice or only once ?

CodePudding user response:

Calling a function calls the function.

await cares about the evaluated value on the right-hand side.

It doesn't stop a function call from being a function call.

Your code is equivalent to:

let promise_from_first_call = readFile("somefile");
let resolved_value_from_first_call = await promise_from_first_call;
let toto = resolved_value_from_first_call.concat(" / ", "toto")

let promise_from_second_call = readFile("somefile");
let resolved_value_from_second_call = await promise_from_first_call;
let titi = resolved_value_from_second_call.concat(" / ", "titi")

Since you are reading the same file twice, could you make it more efficient by only calling the function once - but that is something you have to change, await won't magic that up for you.

let file = await readFile("somefile");
let toto = file.concat(" / ", "toto")
let titi = file.concat(" / ", "titi");

CodePudding user response:

Imagine we define a function that resolves a promise and we call it multiple times through the code using await. Is the promise actually called multiple times or is it called only once and its value is used multiple times (where we await the function) ?

Is readFile() actually reading the file twice or only once ?

To correct the vocabulary slightly:

  • A function like readFile will return a Promise. That Promise might be in the state fulfilled (resolved) or rejected, or it might be pending. All functions marked async will automatically return Promises whether or not you do so explicitly, but non-async functions can return Promises too.
  • It's generally the caller's choice whether to reuse an existing Promise or to create a new one; without seeing readFile we can't know for sure whether it's reading the file twice, but your posted code certainly calls readFile twice. Barring anything clever in readFile or the OS, your file will be read twice.
  • You can't call a promise in any meaningful way: You can call a function like readFile, and if it returns a Promise, you can chain onto it using .then(...) or await it using await in an async function.
  • A Promise will settle (resolve or reject) exactly once and never change state or value after that.
  • You can call .then(...) or await on the same Promise multiple times independently.

Therefore:

// readFile is called twice, so the values are not being reused.
let toto = (await readFile("somefile")).concat(" / ", "toto")
let titi = (await readFile("somefile")).concat(" / ", "titi")
// readFile is called once. You await the Promise twice here, which is
// not necessary, but demonstrates a Promise being reused.
let filePromise = readFile("somefile")
let toto = (await filePromise).concat(" / ", "toto")
let titi = (await filePromise).concat(" / ", "titi")
// readFile is called once, and the Promise it returns is awaited once.
let file = await readFile("somefile")
let toto = file.concat(" / ", "toto")
let titi = file.concat(" / ", "titi")

Side note: If you're winding up with a Promise either way, you might be able to use the newer Blob.text() Promise-based API.

  • Related