From 95a2bfb69ccc36ee81a7c24d20e93554f31d5900 Mon Sep 17 00:00:00 2001 From: wbuezas Date: Sat, 17 Aug 2024 20:25:55 -0300 Subject: [PATCH] Add error interceptor --- src/boot/axios.js | 7 ++ src/js/vn/json-connection.js | 178 ++++++++++++++++++----------------- 2 files changed, 100 insertions(+), 85 deletions(-) diff --git a/src/boot/axios.js b/src/boot/axios.js index 0e0549f0..64de7177 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -35,6 +35,12 @@ const onResponseError = error => { return Promise.reject(error); }; +const jApiErrorInterceptor = error => { + if (error.message) { + notify(error.message, 'negative'); + } +}; + export default boot(({ app }) => { const userStore = useUserStore(); function addToken(config) { @@ -47,6 +53,7 @@ export default boot(({ app }) => { api.interceptors.response.use(response => response, onResponseError); jApi.use(addToken); + jApi.useErrorInterceptor(jApiErrorInterceptor); // for use inside Vue files (Options API) through this.$axios and this.$api diff --git a/src/js/vn/json-connection.js b/src/js/vn/json-connection.js index 21ea745e..51fabfe1 100644 --- a/src/js/vn/json-connection.js +++ b/src/js/vn/json-connection.js @@ -1,70 +1,75 @@ -import { VnObject } from './object' -import { JsonException } from './json-exception' +import { VnObject } from './object'; +import { JsonException } from './json-exception'; /** * Handler for JSON rest connections. */ export class JsonConnection extends VnObject { - _connected = false - _requestsCount = 0 - token = null - interceptors = [] + _connected = false; + _requestsCount = 0; + token = null; + interceptors = []; + errorInterceptor = null; - use (fn) { - this.interceptors.push(fn) + use(fn) { + this.interceptors.push(fn); + } + + useErrorInterceptor(fn) { + this.errorInterceptor = fn; } /** - * Executes the specified REST service with the given params and calls - * the callback when response is received. - * - * @param {String} url The service path - * @param {Object} params The params to pass to the service - * @return {Object} The parsed JSON response - */ - async send (url, params) { - if (!params) params = {} - params.srv = `json:${url}` - return this.sendWithUrl('POST', '.', params) + * Executes the specified REST service with the given params and calls + * the callback when response is received. + * + * @param {String} url The service path + * @param {Object} params The params to pass to the service + * @return {Object} The parsed JSON response + */ + async send(url, params) { + if (!params) params = {}; + params.srv = `json:${url}`; + return this.sendWithUrl('POST', '.', params); } - async sendForm (form) { - const params = {} - const elements = form.elements + async sendForm(form) { + const params = {}; + const elements = form.elements; for (let i = 0; i < elements.length; i++) { if (elements[i].name) { - params[elements[i].name] = elements[i].value + params[elements[i].name] = elements[i].value; } } - return this.sendWithUrl('POST', form.action, params) + return this.sendWithUrl('POST', form.action, params); } - async sendFormMultipart (form) { + async sendFormMultipart(form) { return this.request({ method: 'POST', url: form.action, data: new FormData(form) - }) + }); } - async sendFormData (formData) { + async sendFormData(formData) { return this.request({ method: 'POST', url: '', data: formData - }) + }); } /* - * Called when REST response is received. - */ - async sendWithUrl (method, url, params) { - const urlParams = new URLSearchParams() + * Called when REST response is received. + */ + async sendWithUrl(method, url, params) { + const urlParams = new URLSearchParams(); for (const key in params) { if (params[key] != null) { - urlParams.set(key, params[key]) + urlParams.set(key, params[key]); } } @@ -75,126 +80,129 @@ export class JsonConnection extends VnObject { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } - }) + }); } - async request (config) { - const request = new XMLHttpRequest() - request.open(config.method, config.url, true) + async request(config) { + const request = new XMLHttpRequest(); + request.open(config.method, config.url, true); for (const fn of this.interceptors) { - config = fn(config) + config = fn(config); } - const headers = config.headers + const headers = config.headers; if (headers) { for (const header in headers) { - request.setRequestHeader(header, headers[header]) + request.setRequestHeader(header, headers[header]); } } const promise = new Promise((resolve, reject) => { request.onreadystatechange = () => - this._onStateChange(request, resolve, reject) - }) + this._onStateChange(request, resolve, reject); + }); - request.send(config.data) + request.send(config.data); - this._requestsCount++ + this._requestsCount++; if (this._requestsCount === 1) { - this.emit('loading-changed', true) + this.emit('loading-changed', true); } - return promise + return promise; } - _onStateChange (request, resolve, reject) { + _onStateChange(request, resolve, reject) { if (request.readyState !== 4) { - return + return; } - this._requestsCount-- + this._requestsCount--; if (this._requestsCount === 0) { - this.emit('loading-changed', false) + this.emit('loading-changed', false); } - let data = null - let error = null + let data = null; + let error = null; try { if (request.status === 0) { - const err = new JsonException() + const err = new JsonException(); err.message = - 'The server does not respond, please check your Internet connection' - err.statusCode = request.status - throw err + 'The server does not respond, please check your Internet connection'; + err.statusCode = request.status; + throw err; } - let contentType = null + let contentType = null; try { contentType = request .getResponseHeader('Content-Type') .split(';')[0] - .trim() + .trim(); } catch (err) { - console.warn(err) + console.warn(err); } if (contentType !== 'application/json') { - const err = new JsonException() - err.message = request.statusText - err.statusCode = request.status - throw err + const err = new JsonException(); + err.message = request.statusText; + err.statusCode = request.status; + throw err; } - let json - let jsData + let json; + let jsData; if (request.responseText) { - json = JSON.parse(request.responseText) + json = JSON.parse(request.responseText); } if (json) { - jsData = json.data || json + jsData = json.data || json; } if (request.status >= 200 && request.status < 300) { - data = jsData + data = jsData; } else { - let exception = jsData.exception + let exception = jsData.exception; - const err = new JsonException() - err.statusCode = request.status + const err = new JsonException(); + err.statusCode = request.status; if (exception) { exception = exception .replace(/\\/g, '.') .replace(/Exception$/, '') - .replace(/^Vn\.Web\./, '') + .replace(/^Vn\.Web\./, ''); - err.exception = exception - err.message = jsData.message - err.code = jsData.code - err.file = jsData.file - err.line = jsData.line - err.trace = jsData.trace + err.exception = exception; + err.message = jsData.message; + err.code = jsData.code; + err.file = jsData.file; + err.line = jsData.line; + err.trace = jsData.trace; } else { - err.message = request.statusText + err.message = request.statusText; } - throw err + throw err; } } catch (e) { - data = null - error = e + data = null; + error = e; } if (error) { - this.emit('error', error) - reject(error) + if (this.errorInterceptor) { + this.errorInterceptor(error); + } + this.emit('error', error); + reject(error); } else { - resolve(data) + resolve(data); } } }