Skip to content

Commit e96c9a4

Browse files
committed
pull out various parts of cachedFetch into other functions
1 parent 4c0dfbf commit e96c9a4

File tree

1 file changed

+79
-42
lines changed

1 file changed

+79
-42
lines changed

modules/fetch/cached.js

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -100,63 +100,64 @@ async function getItem(key: string): Promise<GetItemResult> {
100100
}
101101
}
102102

103-
// Requests an URL and retrieves it from the cache if possible
104-
export async function cachedFetch(request: Request): Promise<Response> {
105-
let {url} = request
103+
// Handles the case of no-data-yet-cached
104+
async function handleInitialFetch(args: {request: Request, key: string}) {
105+
let {request, key} = args
106106

107-
let cachePolicyRequest = requestForCachePolicy(request)
107+
debug && console.log(`fetch(${request.url}): no policy cached; fetching`)
108108

109-
let key = `urlcache:${url}`
110-
let {response: oldResponse, policy: oldPolicy} = await getItem(key)
109+
// I explicitly want errors here to propagate. Why? Bundled data will have
110+
// an expired policy stored, so it won't hit this branch. Thus, the only
111+
// requests in here will have nothing to fall back to, so we need some way
112+
// to signal that an error happened.
113+
let response = await fetch(request)
111114

112-
if (process.env.NODE_ENV === 'development') {
113-
let bundledResponse = await AsyncStorage.getItem(`${ROOT}:${key}:bundled`)
114-
if (bundledResponse) {
115-
debug &&
116-
console.log(
117-
`fetch(${request.url}): in dev mode; returning bundled data`,
118-
)
119-
let {body, ...init} = JSON.parse(bundledResponse)
120-
return new Response(body, init)
121-
}
122-
}
115+
let cachePolicyRequest = requestForCachePolicy(request)
116+
let cachePolicyResponse = responseForCachePolicy(response)
123117

124-
// If nothing has ever been cached, go fetch it
125-
if (!oldPolicy) {
126-
debug && console.log(`fetch(${request.url}): no policy cached; fetching`)
118+
let policy = new CachePolicy(cachePolicyRequest, cachePolicyResponse)
127119

128-
let response = await fetch(request)
129-
let cachePolicyResponse = responseForCachePolicy(response)
120+
if (policy.storable()) {
121+
debug && console.log(`fetch(${request.url}): caching`)
122+
await cacheItem({key, response, policy})
123+
} else {
124+
debug && console.log(`fetch(${request.url}): not cachable`)
125+
}
130126

131-
let policy = new CachePolicy(cachePolicyRequest, cachePolicyResponse)
127+
return response
128+
}
132129

133-
if (policy.storable()) {
134-
debug && console.log(`fetch(${request.url}): caching`)
135-
await cacheItem({key, response, policy})
136-
} else {
137-
debug && console.log(`fetch(${request.url}): not cachable`)
138-
}
130+
type HandlePartialFetchArgs = {
131+
request: Request,
132+
oldResponse: Response,
133+
oldPolicy: CachePolicy,
134+
key: string,
135+
}
139136

140-
return response
141-
}
137+
// Handles the case of cached-and-fresh data
138+
function handleCachedButStillFresh(args: HandlePartialFetchArgs) {
139+
let {request, oldResponse, oldPolicy} = args
142140

143-
// If we can re-use the cached data, return it; otherwise, we're serving requests from the cache
144-
if (oldPolicy.satisfiesWithoutRevalidation(cachePolicyRequest)) {
145-
debug && console.log(`fetch(${request.url}): fresh; returning`)
146-
oldResponse.headers = new Headers(oldPolicy.responseHeaders())
147-
return oldResponse
148-
}
141+
debug && console.log(`fetch(${request.url}): fresh; returning`)
142+
oldResponse.headers = new Headers(oldPolicy.responseHeaders())
143+
return oldResponse
144+
}
149145

150-
// Update the request to ask the origin server if the cached response can be used
151-
request.headers = new Headers(
152-
oldPolicy.revalidationHeaders(cachePolicyRequest),
153-
)
146+
// Handles the case of cached-but-stale data
147+
async function handleStale(args: HandlePartialFetchArgs) {
148+
let {request, oldResponse, oldPolicy, key} = args
154149

155150
debug && console.log(`fetch(${request.url}): stale; validating`)
156151

152+
let cachePolicyRequest = requestForCachePolicy(request)
153+
157154
let newResponse = null
158155
try {
159-
// Send request to the origin server. The server may respond with status 304
156+
// Update the request to ask the origin server if the cached response can be used
157+
let newHeaders = oldPolicy.revalidationHeaders(cachePolicyRequest)
158+
request.headers = new Headers(newHeaders)
159+
160+
// Send request to the origin server. The server may respond with status 304.
160161
newResponse = await fetch(request)
161162
} catch (error) {
162163
// "A fetch() promise only rejects when a network error is encountered [...] not on HTTP errors such as 404"
@@ -200,3 +201,39 @@ export async function cachedFetch(request: Request): Promise<Response> {
200201

201202
return response
202203
}
204+
205+
// Returns the bundled response when in development
206+
function handleBundledInDev(request: Request, bundledResponse: string) {
207+
debug &&
208+
console.log(`fetch(${request.url}): in dev mode; returning bundled data`)
209+
let {body, ...init} = JSON.parse(bundledResponse)
210+
return new Response(body, init)
211+
}
212+
213+
// Requests an URL and retrieves it from the cache if possible
214+
export async function cachedFetch(request: Request): Promise<Response> {
215+
let {url} = request
216+
217+
let key = `urlcache:${url}`
218+
let {response: oldResponse, policy: oldPolicy} = await getItem(key)
219+
220+
// If we're in dev, and there's bundled data, return it
221+
if (process.env.NODE_ENV === 'development') {
222+
let bundledResponse = await AsyncStorage.getItem(`${ROOT}:${key}:bundled`)
223+
if (bundledResponse) {
224+
return handleBundledInDev(request, bundledResponse)
225+
}
226+
}
227+
228+
// If nothing has ever been cached, go fetch it
229+
if (!oldPolicy) {
230+
return handleInitialFetch({request, key})
231+
}
232+
233+
// If we can re-use the cached data, return it; otherwise, we're serving requests from the cache
234+
if (oldPolicy.satisfiesWithoutRevalidation(requestForCachePolicy(request))) {
235+
return handleCachedButStillFresh({request, oldResponse, oldPolicy, key})
236+
}
237+
238+
return handleStale({request, oldResponse, oldPolicy, key})
239+
}

0 commit comments

Comments
 (0)