/** * Callback for passing back result data. * @callback updateCallback * @param {string} result - A success or error string */ /** * Callback to run after all is done. * @callback finalCallback */ /** * A function that handles parsing of fetch requests * @todo add support for better error messaging on non-json responses * @param {object} options - All the fun stuff. * @param {function} options.fetch - The http fetch call * @param {updateCallback} options.successCb - The function to call on success. * @param {updateCallback} options.errorCb - The function to call on error. * @param {finalCallback} options.finallyCb - The function to be called when all is done. * @example * apiCall({ * fetch: () => fetch('https://bananas.com?id=1'), * updateCallback: banana => this.setState({ banana }), * errorCallback: error => this.setState({ error }), * finallyCb: () => this.setState({ loading: false }) * }) */ export const apiCall = async ({ fetch, successCb, errorCb, finallyCb }) => { try { const resp = await fetch(); const contentType = resp.headers && resp.headers.get('content-type'); if (resp.ok || (contentType && contentType.includes('application/json'))) { const json = await resp.json(); json.error ? errorCb(`ERROR: ${json.error.message}. CODE: ${json.error.code}`) : successCb(json); } else { throw new Error(`${resp.statusText}:${resp.status}`); } } catch (error) { errorCb(error.message || error); } finally { finallyCb && finallyCb(); } };