I have the following JS function that fetches data and put in a window.data
property:
function fetchData() {
if (window.data) {
return Promise.resolve(window.data)
} else {
return fetch('http://example.com/data.js')
.then(response => response.json())
.then(json => window.data = json)
}
}
The code works fine.
However, when there are two concurrent calls to that function, the first call to fetchData
will fire the fetch
.
Because the fetch
can take some time, a second call to fetchData
won’t find anything in the window.data
and fire the same fetch
.
Question :
How can I send an elegant pending
signal to the second call and return the result as a resolved promise ?
Unless a promise-based solution is not possible, is there any another approach I can dig ?
The ideal solution should not block the second block but instead deal with it asynchronously with promises
Regards
I tried a mutex-based solution but it seemed over complicated.
2
Answers
Use a helper variable
like window.isResolved
Since the result is being attached to window, and would-be caller may check that first. But more generally, return a promise from both branches of the conditional. That promise is your elegant representation of something pending. When the data is present, the
resolve
branch runs immediately…edit A commenter suggests that the OP might be aiming to avoid a second call to fetch. One way is to use the promise itself as a sentinel value.
Restating (not endorsing using
window
, but for wherever the value is kept)…Callers who await (or then) the result of this function will either get the already resolved promise (which will harmlessly resolve again to the data), or the existing deferred result without triggering another fetch.