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 markedasync
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 callsreadFile
twice. Barring anything clever inreadFile
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 usingawait
in anasync
function. - A Promise will settle (resolve or reject) exactly once and never change state or value after that.
- You can call
.then(...)
orawait
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.