0
1
Fork 0

Add error interceptor

This commit is contained in:
William Buezas 2024-08-17 20:25:55 -03:00
parent 87c151c057
commit 95a2bfb69c
2 changed files with 100 additions and 85 deletions

View File

@ -35,6 +35,12 @@ const onResponseError = error => {
return Promise.reject(error); return Promise.reject(error);
}; };
const jApiErrorInterceptor = error => {
if (error.message) {
notify(error.message, 'negative');
}
};
export default boot(({ app }) => { export default boot(({ app }) => {
const userStore = useUserStore(); const userStore = useUserStore();
function addToken(config) { function addToken(config) {
@ -47,6 +53,7 @@ export default boot(({ app }) => {
api.interceptors.response.use(response => response, onResponseError); api.interceptors.response.use(response => response, onResponseError);
jApi.use(addToken); jApi.use(addToken);
jApi.useErrorInterceptor(jApiErrorInterceptor);
// for use inside Vue files (Options API) through this.$axios and this.$api // for use inside Vue files (Options API) through this.$axios and this.$api

View File

@ -1,17 +1,22 @@
import { VnObject } from './object' import { VnObject } from './object';
import { JsonException } from './json-exception' import { JsonException } from './json-exception';
/** /**
* Handler for JSON rest connections. * Handler for JSON rest connections.
*/ */
export class JsonConnection extends VnObject { export class JsonConnection extends VnObject {
_connected = false _connected = false;
_requestsCount = 0 _requestsCount = 0;
token = null token = null;
interceptors = [] interceptors = [];
errorInterceptor = null;
use (fn) { use(fn) {
this.interceptors.push(fn) this.interceptors.push(fn);
}
useErrorInterceptor(fn) {
this.errorInterceptor = fn;
} }
/** /**
@ -22,49 +27,49 @@ export class JsonConnection extends VnObject {
* @param {Object} params The params to pass to the service * @param {Object} params The params to pass to the service
* @return {Object} The parsed JSON response * @return {Object} The parsed JSON response
*/ */
async send (url, params) { async send(url, params) {
if (!params) params = {} if (!params) params = {};
params.srv = `json:${url}` params.srv = `json:${url}`;
return this.sendWithUrl('POST', '.', params) return this.sendWithUrl('POST', '.', params);
} }
async sendForm (form) { async sendForm(form) {
const params = {} const params = {};
const elements = form.elements const elements = form.elements;
for (let i = 0; i < elements.length; i++) { for (let i = 0; i < elements.length; i++) {
if (elements[i].name) { 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({ return this.request({
method: 'POST', method: 'POST',
url: form.action, url: form.action,
data: new FormData(form) data: new FormData(form)
}) });
} }
async sendFormData (formData) { async sendFormData(formData) {
return this.request({ return this.request({
method: 'POST', method: 'POST',
url: '', url: '',
data: formData data: formData
}) });
} }
/* /*
* Called when REST response is received. * Called when REST response is received.
*/ */
async sendWithUrl (method, url, params) { async sendWithUrl(method, url, params) {
const urlParams = new URLSearchParams() const urlParams = new URLSearchParams();
for (const key in params) { for (const key in params) {
if (params[key] != null) { if (params[key] != null) {
urlParams.set(key, params[key]) urlParams.set(key, params[key]);
} }
} }
@ -75,126 +80,129 @@ export class JsonConnection extends VnObject {
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
} }
}) });
} }
async request (config) { async request(config) {
const request = new XMLHttpRequest() const request = new XMLHttpRequest();
request.open(config.method, config.url, true) request.open(config.method, config.url, true);
for (const fn of this.interceptors) { for (const fn of this.interceptors) {
config = fn(config) config = fn(config);
} }
const headers = config.headers const headers = config.headers;
if (headers) { if (headers) {
for (const header in headers) { for (const header in headers) {
request.setRequestHeader(header, headers[header]) request.setRequestHeader(header, headers[header]);
} }
} }
const promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
request.onreadystatechange = () => 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) { 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) { if (request.readyState !== 4) {
return return;
} }
this._requestsCount-- this._requestsCount--;
if (this._requestsCount === 0) { if (this._requestsCount === 0) {
this.emit('loading-changed', false) this.emit('loading-changed', false);
} }
let data = null let data = null;
let error = null let error = null;
try { try {
if (request.status === 0) { if (request.status === 0) {
const err = new JsonException() const err = new JsonException();
err.message = err.message =
'The server does not respond, please check your Internet connection' 'The server does not respond, please check your Internet connection';
err.statusCode = request.status err.statusCode = request.status;
throw err throw err;
} }
let contentType = null let contentType = null;
try { try {
contentType = request contentType = request
.getResponseHeader('Content-Type') .getResponseHeader('Content-Type')
.split(';')[0] .split(';')[0]
.trim() .trim();
} catch (err) { } catch (err) {
console.warn(err) console.warn(err);
} }
if (contentType !== 'application/json') { if (contentType !== 'application/json') {
const err = new JsonException() const err = new JsonException();
err.message = request.statusText err.message = request.statusText;
err.statusCode = request.status err.statusCode = request.status;
throw err throw err;
} }
let json let json;
let jsData let jsData;
if (request.responseText) { if (request.responseText) {
json = JSON.parse(request.responseText) json = JSON.parse(request.responseText);
} }
if (json) { if (json) {
jsData = json.data || json jsData = json.data || json;
} }
if (request.status >= 200 && request.status < 300) { if (request.status >= 200 && request.status < 300) {
data = jsData data = jsData;
} else { } else {
let exception = jsData.exception let exception = jsData.exception;
const err = new JsonException() const err = new JsonException();
err.statusCode = request.status err.statusCode = request.status;
if (exception) { if (exception) {
exception = exception exception = exception
.replace(/\\/g, '.') .replace(/\\/g, '.')
.replace(/Exception$/, '') .replace(/Exception$/, '')
.replace(/^Vn\.Web\./, '') .replace(/^Vn\.Web\./, '');
err.exception = exception err.exception = exception;
err.message = jsData.message err.message = jsData.message;
err.code = jsData.code err.code = jsData.code;
err.file = jsData.file err.file = jsData.file;
err.line = jsData.line err.line = jsData.line;
err.trace = jsData.trace err.trace = jsData.trace;
} else { } else {
err.message = request.statusText err.message = request.statusText;
} }
throw err throw err;
} }
} catch (e) { } catch (e) {
data = null data = null;
error = e error = e;
} }
if (error) { if (error) {
this.emit('error', error) if (this.errorInterceptor) {
reject(error) this.errorInterceptor(error);
}
this.emit('error', error);
reject(error);
} else { } else {
resolve(data) resolve(data);
} }
} }
} }