Cleanup AbstractFetch

and added fetchJSON mockup code for error handling regarding issue #49
This commit is contained in:
djmaze 2021-01-05 13:58:50 +01:00
parent 4723e1241e
commit fa7ea413dc
2 changed files with 176 additions and 172 deletions

View file

@ -17,6 +17,9 @@ updateToken = data => {
checkResponseError = data => {
const err = data ? data.ErrorCode : null;
if (Notification.InvalidToken === err && 10 < ++iTokenErrorCount) {
rl.logoutReload();
} else {
if ([
Notification.AuthError,
Notification.AccessError,
@ -30,31 +33,18 @@ checkResponseError = data => {
) {
++iJsonErrorCount;
}
if (Notification.InvalidToken === err) {
++iTokenErrorCount;
}
if (10 < iTokenErrorCount) {
rl.logoutReload();
}
if (window.rl && (data.ClearAuth || data.Logout || 7 < iJsonErrorCount)) {
rl.hash.clear();
if (!data.ClearAuth) {
rl.logoutReload();
}
}
}
},
oRequests = {};
oRequests = {},
addEventListener('unload', () => bUnload = true);
class AbstractFetchRemote
{
abort(sAction, bClearOnly) {
abort = (sAction, bClearOnly) => {
if (oRequests[sAction]) {
if (!bClearOnly && oRequests[sAction].abort) {
// oRequests[sAction].__aborted = true;
@ -64,7 +54,36 @@ class AbstractFetchRemote
oRequests[sAction] = null;
delete oRequests[sAction];
}
},
fetchJSON = (action, sGetAdd, params, timeout, jsonCallback) => {
sGetAdd = pString(sGetAdd);
params = params || {};
params.Action = action;
let init = {};
if (window.AbortController) {
abort(action);
const controller = new AbortController();
timeout && setTimeout(() => controller.abort(), timeout);
oRequests[action] = controller;
init.signal = controller.signal;
}
return rl.fetchJSON(getURL(sGetAdd), init, sGetAdd ? null : params)
.then(jsonCallback)
.catch(err => {
if (err.name == 'AbortError') { // handle abort()
err = Notification.JsonAbort;
}
return Promise.reject(err);
});
};
addEventListener('unload', () => bUnload = true);
export class AbstractFetchRemote
{
abort(sAction, bClearOnly) {
abort(sAction, bClearOnly);
return this;
}
@ -78,21 +97,17 @@ class AbstractFetchRemote
*/
defaultRequest(fCallback, sAction, params, iTimeout, sGetAdd, abortActions) {
params = params || {};
params.Action = sAction;
sGetAdd = pString(sGetAdd);
const start = Date.now();
const start = Date.now(),
action = params.Action || '';
if (action && abortActions) {
abortActions.forEach(actionToAbort => this.abort(actionToAbort));
if (sAction && abortActions) {
abortActions.forEach(actionToAbort => abort(actionToAbort));
}
return rl.fetchJSON(getURL(sGetAdd), {
signal: this.createAbort(action, undefined === iTimeout ? 30000 : pInt(iTimeout))
}, sGetAdd ? null : params
).then(data => {
return fetchJSON(sAction, sGetAdd,
params,
undefined === iTimeout ? 30000 : pInt(iTimeout),
data => {
let cached = false;
if (data) {
if (data.Time) {
@ -103,11 +118,11 @@ class AbstractFetchRemote
}
let sType = 'success';
if (action && oRequests[action]) {
if (oRequests[action].__aborted) {
if (sAction && oRequests[sAction]) {
if (oRequests[sAction].__aborted) {
sType = 'abort';
}
this.abort(action, true);
abort(sAction, true);
}
const fCall = () => {
@ -115,10 +130,12 @@ class AbstractFetchRemote
sType = StorageResultType.Unload;
}
if (StorageResultType.Success === sType && data && !data.Result) {
checkResponseError(data);
} else if (StorageResultType.Success === sType && data && data.Result) {
if (StorageResultType.Success === sType && data) {
if (data.Result) {
iJsonErrorCount = iTokenErrorCount = 0;
} else {
checkResponseError(data);
}
}
if (fCallback) {
@ -126,7 +143,7 @@ class AbstractFetchRemote
sType,
StorageResultType.Success === sType ? data : null,
cached,
action,
sAction,
params
);
}
@ -135,27 +152,19 @@ class AbstractFetchRemote
switch (sType) {
case 'success':
sType = StorageResultType.Success;
fCall();
break;
case 'abort':
sType = StorageResultType.Abort;
fCall();
break;
default:
sType = StorageResultType.Error;
setTimeout(fCall, 300);
break;
}
if (StorageResultType.Error === sType) {
setTimeout(fCall, 300);
} else {
fCall();
}
}).catch(err => {
if (err.name == 'AbortError') { // handle abort()
err = Notification.JsonAbort;
}
return Promise.reject(err);
});
);
}
/**
@ -182,18 +191,6 @@ class AbstractFetchRemote
});
}
createAbort(action, timeout) {
if (window.AbortController) {
this.abort(action);
const controller = new AbortController();
if (timeout) {
setTimeout(() => controller.abort(), timeout);
}
oRequests[action] = controller;
return controller.signal;
}
}
fastResolve(mData) {
return Promise.resolve(mData);
}
@ -201,25 +198,17 @@ class AbstractFetchRemote
setTrigger(trigger, value) {
if (trigger) {
value = !!value;
(Array.isArray(trigger) ? trigger : [trigger]).forEach((fTrigger) => {
if (fTrigger) {
fTrigger(value);
}
(Array.isArray(trigger) ? trigger : [trigger]).forEach(fTrigger => {
fTrigger && fTrigger(value);
});
}
}
postRequest(action, fTrigger, params, timeOut) {
params = params || {};
params.Action = action;
this.setTrigger(fTrigger, true);
return rl.fetchJSON(getURL(), {
signal: this.createAbort(action, pInt(timeOut, 30000))
}, params
).then(data => {
this.abort(action, true);
return fetchJSON(action, '', params, pInt(timeOut, 30000),
data => {
abort(action, true);
if (!data) {
return Promise.reject(Notification.JsonParse);
@ -253,13 +242,7 @@ class AbstractFetchRemote
}
return data;
}).catch(err => {
if (err.name == 'AbortError') { // handle abort()
return Promise.reject(Notification.JsonAbort);
}
return Promise.reject(err);
});
);
}
}
export { AbstractFetchRemote, AbstractFetchRemote as default };

35
dev/bootstrap.js vendored
View file

@ -90,15 +90,13 @@ export default (App) => {
cache: 'no-cache',
redirect: 'error',
referrerPolicy: 'no-referrer',
credentials: 'same-origin'
credentials: 'same-origin',
headers: {}
}, init);
init.headers.Accept = 'application/json';
if (postData) {
init.method = 'POST';
init.headers = {
// 'Content-Type': 'application/json'
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
};
init.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
postData.XToken = rl.settings.app('token');
// init.body = JSON.stringify(postData);
const formData = new FormData(),
@ -115,7 +113,30 @@ export default (App) => {
init.body = new URLSearchParams(formData);
}
return fetch(resource, init).then(response => response.json());
return fetch(resource, init).then(response => {
if (!response.ok) {
// return Promise.reject('Network response error: ' + response.status);
throw new Error('Network response error: ' + response.status);
}
/* TODO: use this for non-developers?
response.clone()
let data = response.text();
try {
return JSON.parse(data);
} catch (e) {
console.error(e);
// console.log(data);
return Promise.reject(Notification.JsonParse);
return {
Result: false,
ErrorCode: 952, // Notification.JsonParse
ErrorMessage: e.message,
ErrorMessageAdditional: data
}
}
*/
return response.json();
});
};
window.__APP_BOOT = fErrorCallback => {