Writing an Adapter for Fetch API
It seems that there is no such project that does not need to make requests to the server. And it is always a good idea to write a separate abstraction to describe such communication. This not only adds readability and reusability to the code, but also makes it possible to quickly and efficiently write tests for such functionality. class NetworkService { constructor(private readonly fetch: typeof fetch) {} getUser: (): Promise<IUser> => this.fetch('/api/user').then(d => d.json()) } function getUsername(api: Pick<NetworkService, 'getUser'>) { return api.getUser().then(user => user.name); } test('getUsername', async () => { const name = await getUsername({ getUser: () => Promise.resolve({ name: 'test' } as IUser) }); expect(name).toBe('test'); }); And for an average project, this approach will be sufficient. But sometimes there are requirements that you need to redefine the fetch itself. For example, in our project, we are developing an extension for the browser and we want to make requests through the serviceWorker. And there is a requirement to reimplement the Fetch API. As we know, fetch returns a Response primitive, for the creation of which you need to pass the ReadableStream as the first argument, and the response characteristics as the second. Thus, we can use the following construction. ...