Last active
September 18, 2022 23:51
-
-
Save panzerdp/1312bcd5f455fa409d2aced844cad96f to your computer and use it in GitHub Desktop.
An extensible fetch() implementation that uses the decorator pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ResponseWithData = Response & { data?: any }; | |
interface Fetcher { | |
run(input: RequestInfo, init?: RequestInit): Promise<ResponseWithData>; | |
} | |
class BasicFetcher implements Fetcher { | |
async run(input: RequestInfo, init?: RequestInit): Promise<ResponseWithData> { | |
return await fetch(input, init); | |
} | |
} | |
class JsonFetcherDecorator implements Fetcher { | |
private decoratee: Fetcher; | |
constructor(decoratee: Fetcher) { | |
this.decoratee = decoratee; | |
} | |
async run(input: RequestInfo, init?: RequestInit): Promise<ResponseWithData> { | |
const response = await this.decoratee.run(input, init); | |
const json = await response.json(); | |
response.data = json; | |
return response; | |
} | |
} | |
const TIMEOUT = 8000; // 8 seconds | |
class TimeoutFetcherDecorator implements Fetcher { | |
private decoratee: Fetcher; | |
constructor(decoratee: Fetcher) { | |
this.decoratee = decoratee; | |
} | |
async run(input: RequestInfo, init?: RequestInit): Promise<ResponseWithData> { | |
const controller = new AbortController(); | |
const id = setTimeout(() => controller.abort(), TIMEOUT); | |
const response = await this.decoratee.run(input, { | |
...init, | |
signal: controller.signal | |
}); | |
clearTimeout(id); | |
return response; | |
} | |
} | |
const fetcher = new TimeoutFetcherDecorator( | |
new JsonFetcherDecorator( | |
new BasicFetcher() | |
) | |
); | |
export const decoratedFetch = fetcher.run.bind(fetcher); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: