ajax-json-http-clinet
Version:
Completely handled http request to receive and send json data to/from server
208 lines (197 loc) • 7.98 kB
JavaScript
export default class AjaxClient {
constructor(api_base_url, time_limit=0, composer=undefined){
if(!time_limit){
time_limit = 20;
}
this.api_server_url = api_base_url;
this.fetch_timeout = time_limit;
let composer_template = {
on_api_request_init: function(){},
on_api_success: function(){},
on_api_error: function(){},
on_api_failed: function(){},
}
if(!composer){
composer = composer_template;
}
else{
if(!composer.on_api_request_init){ composer.on_api_request_init = composer_template.on_api_request_init }
if(!composer.on_api_success){ composer.on_api_success = composer_template.on_api_success }
if(!composer.on_api_error){ composer.on_api_error = composer_template.on_api_error }
if(!composer.on_api_failed){ composer.on_api_failed = composer_template.on_api_failed }
}
this.composer = composer;
}
async set_headers(fetch_options, headers){
fetch_options.headers = headers;
}
async on_api_response(res_type, endpoint, message=''){
console.log('Api response => '+ res_type, this.api_server_url+ endpoint, message);
if(res_type == 'success'){
this.composer.on_api_success(endpoint, message);
}
else if(res_type == 'error'){
this.composer.on_api_error(endpoint, message);
}
if(res_type == 'failed'){
this.composer.on_api_failed(endpoint, message);
}
}
async fetch_request(endpoint, method, req_data={}, headers={}, time_limit=0) {
let obj_this = this;
let api_base_url = this.api_server_url;
let server_endpoint = api_base_url + endpoint;
let raw_result = {
status: 'failed', code: 512, message: 'No result',
server_endpoint: server_endpoint, endpoint: endpoint.substr(1)
}
const abort_controller = new AbortController();
let max_request_wait = (time_limit ? time_limit : obj_this.fetch_timeout) * 1000;
const timeoutId = setTimeout(() => abort_controller.abort(), max_request_wait);
this.composer.on_api_request_init(endpoint, max_request_wait);
method = method.toLowerCase()
let fetch_options = {method: method};
if(Object.keys(headers).length){
fetch_options.headers = headers;
}
if(method == 'ping'){
server_endpoint = endpoint;
fetch_options.method = 'get';
}
else{
await this.set_headers(fetch_options, headers);
if(method == 'get'){
fetch_options.data = req_data;
}
else{
fetch_options.body = JSON.stringify(req_data);
}
}
fetch_options.signal = abort_controller.signal;
return fetch(server_endpoint, fetch_options).then(api_response=>{
if(!api_response.status){
if(api_response.detail)
{
raw_result.message = 'Failed becaused => ' + api_response.detail;
}
else{
if(!api_response.message)
{
raw_result.message = 'Invalid access ';
}
}
return raw_result;
}
if(api_response.status == 200){
if(method == 'ping'){
return {status: 'ok'}
}
return api_response.json().then(json_result=> json_result);
}
else{
return {status: 'failed', message: 'Error thrown '+api_response.status+' by api'}
}
}).then(api_result=>{
clearTimeout(timeoutId);
for(let key in api_result){
raw_result[key] = api_result[key];
}
let processed_result = obj_this.format_result(endpoint, raw_result);
if(processed_result.status == 'ok' || processed_result.status == 'success'){
this.on_api_response('success', endpoint);
}
else{
this.on_api_response('error', endpoint, processed_result.message);
}
return processed_result;
}).catch(er_not_accessible => {
clearTimeout(timeoutId);
er_not_accessible = '' + er_not_accessible;
raw_result.status = 'failed';
if(er_not_accessible.indexOf('AbortError') > -1){
raw_result.message = ('Timed out after '+ (obj_this.fetch_timeout)+ ' seconds');
raw_result.code = 513;
}
else if(er_not_accessible.indexOf('Network request failed') > -1)
{
raw_result.message = 'Network request failed to reach';
}
else if(er_not_accessible.indexOf('JSON Parse error')){
raw_result.message = ('Api response is not a valid json');
if(!raw_result.code)
{
raw_result.code = 500;
}
}
else{
raw_result.message = 'Error in fetch => ' + er_not_accessible;
}
this.on_api_response('failed', endpoint, raw_result.message);
return raw_result;
}).catch(on_error=>{
raw_result.message = 'Error 1 in catch => ' +on_error
this.on_api_response('failed', endpoint, raw_result.message);
return {status: 'failed', message: raw_result.message};
}).catch(er_catch=>{
raw_result.message = 'Error 2 in catch => ' +er_catch
return {status: 'failed', message: raw_result.message};
}).finally(x => {
});
}
format_result(endpoint, processed_result){
if(processed_result.status == 'success'){
processed_result.status = 'ok';
}
if(processed_result.status != 'ok'){
processed_result.status = 'failed';
if(!processed_result.message && processed_result.error){
processed_result.message = processed_result.error;
}
if(!processed_result.message && processed_result.data){
processed_result.message = processed_result.data;
}
if(!processed_result.message){
processed_result.message = 'Invalid response';
}
processed_result.message += ' in => '+ endpoint.substr(1);
processed_result.status = 'error';
}
else{
if(processed_result.message == 'No result'){
processed_result.message = "Success at " + endpoint.substr(1);
}
}
return processed_result;
}
set_server_url(server_url){
this.api_server_url = server_url;
}
async ping(url, max_time=0){
return this.fetch_request(url, 'ping', {}, max_time);
}
async get_data(endpoint, req_data={}, headers={}, max_time=0){
return this.fetch_request(endpoint, 'GET', req_data, headers, max_time);
}
async post_data(endpoint, req_data={}, headers={}, max_time=0){
try{
if(req_data.files){
let req_data = new FormData();
for (let key in req_data) {
req_data.append(key, req_data[key]);
}
req_data.files.forEach((file, index) => {
req_data.append('files', {
name: 'file' + index,
uri: file
});
});
}
return this.fetch_request(endpoint, 'POST', req_data, headers, max_time);
}
catch(post_er){
return new Promise(function (resolve, reject) {
reject(post_er, endpoint);
});
}
}
}