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
readFilewill return a Promise. That Promise might be in the state fulfilled (resolved) or rejected, or it might be pending. All functions markedasyncwill automatically return Promises whether or not you do so explicitly, but non-asyncfunctions 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
readFilewe can't know for sure whether it's reading the file twice, but your posted code certainly callsreadFiletwice. Barring anything clever inreadFileor 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 usingawaitin anasyncfunction. - A Promise will settle (resolve or reject) exactly once and never change state or value after that.
- You can call
.then(...)orawaiton 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.
