I have three URLs I need to access in my code. The first two will always be accessed, but the third one might be accessed zero, one or two times. As all URLs take a lot of processing, I don’t want to access the third one if I don’t have to.
My code is something like this:
fetch('a')
.then(response => response.json() }
.then(data => {
if (data.value == '1') {
fetch('c')
.then(response => response.json() }
.then(data => console.log('through a', data));
}
}
fetch('b')
.then(response => response.json() }
.then(data => {
if (data.value == '1') {
fetch('c')
.then(response => response.json() }
.then(data => console.log('through a', data));
}
}
So, the result from URL ‘c’ might be needed zero, one or two times. Both a, b and c can take a while to process, so either ‘a’ or ‘b’ might be first accessing ‘c’. In case both need to return ‘c’, I don’t want a second fetch to be performed, I want the second one to return the value already fetched by the first one.
My thought was to do it like this:
const c = () => {
return new Promise(() => {
fetch('c')
.then(response => response.json() };
})
}
fetch('a')
.then(response => response.json() }
.then(data => {
if (data.value == '1') {
c().then(data => console.log('through a', data));
}
}
fetch('b')
.then(response => response.json() }
.then(data => {
if (data.value == '1') {
c().then(data => console.log('through b', data));
}
}
But this still causes ‘c’ to be accessed twice if both ‘a’ and ‘b’ return ‘1’.
How should I do this instead?
3
Answers
Use
Promise.all()
to check the result of both fetches, then fetch fromc
if either of them returns the value 1.Sounds like you want to lazily call "c" and at most once.
Something like this should suffice
The Nullish coalescing assignment (??=) means
cPromise
will only be assigned once whenc()
is first called. It also meansfetch("c")
will only be called at most one time.The last time I experimented with this, I think what I observed is that if one
fetch('c')
is already pending but doesn’t have a response yet, then a second call tofetch('c')
will not use the browser cache and instead start a second request (maybe do some experiments to see if this is correct). In this case, you can manually cache thec
request by storing the promise likelet cPromise = null
and replacing allfetch('c').then()
with:This can be nice if you’ll eventually need to do this for a bunch of different urls that could be saved in a Map. Keep in mind with this solution you’ll make one
'c'
request, but bothcPromise.then()
‘s will execute, so only do this if that’s your desired behavior.