Created
December 12, 2021 13:33
-
-
Save belonog/e8b526a7057b23caed544fa6d4243bb7 to your computer and use it in GitHub Desktop.
fetch data and format response
This file contains hidden or 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
| export function fetcher<T>(resource: RequestInfo, init: RequestInit = {}): Promise<T> { | |
| return fetch(resource, { | |
| ...init, | |
| credentials: 'include', | |
| }).then( | |
| (response) => { | |
| return getJSON(response) | |
| .catch((err) => { | |
| throw new InternalError(err.message); | |
| }) | |
| .then((json) => { | |
| if (!response.ok) { | |
| throw new ApiError(response.status, response.statusText, json); | |
| } | |
| return json; | |
| }); | |
| }, | |
| (error) => { | |
| throw new RequestError(error); | |
| } | |
| ); | |
| } | |
| /** | |
| * Error class for a custom `payload` or `meta` function throwing | |
| * | |
| * @class InternalError | |
| * @access public | |
| * @param {string} message - the error message | |
| */ | |
| export class InternalError extends Error { | |
| name: 'InternalError'; | |
| message: string; | |
| constructor(message: string) { | |
| super(); | |
| this.name = 'InternalError'; | |
| this.message = message; | |
| } | |
| } | |
| /** | |
| * Error class for an error raised trying to make an API call | |
| * | |
| * @class RequestError | |
| * @access public | |
| * @param {string} message - the error message | |
| */ | |
| export class RequestError extends Error { | |
| name: 'RequestError'; | |
| message: string; | |
| constructor(message: string) { | |
| super(); | |
| this.name = 'RequestError'; | |
| this.message = message; | |
| } | |
| } | |
| /** | |
| * Error class for an API response outside the 200 range | |
| * | |
| * @class ApiError | |
| * @access public | |
| * @param {number} status - the status code of the API response | |
| * @param {string} statusText - the status text of the API response | |
| * @param {object} response - the parsed JSON response of the API server if the | |
| * 'Content-Type' header signals a JSON response | |
| */ | |
| export class ApiError<T = any> extends Error { | |
| name: 'ApiError'; | |
| status: number; | |
| statusText: string; | |
| response: T; | |
| message: string; | |
| constructor(status: number, statusText: string, response: T) { | |
| super(); | |
| this.name = 'ApiError'; | |
| this.status = status; | |
| this.statusText = statusText; | |
| this.response = response; | |
| this.message = `${status} - ${statusText}`; | |
| } | |
| } | |
| /** | |
| * Extract JSON body from a server response | |
| * | |
| * @function getJSON | |
| * @access public | |
| * @param {object} res - A raw response object | |
| * @returns {promise|undefined} | |
| */ | |
| async function getJSON(res: Response): Promise<any> { | |
| const contentType = res.headers.get('Content-Type'); | |
| const emptyCodes = [204, 205]; | |
| if (emptyCodes.includes(res.status) === false && contentType && contentType.includes('json')) { | |
| return await res.json(); | |
| } else { | |
| return await Promise.resolve(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment