From 8883eacd2a5e2f3f5637a6b71123dfcb2a64c3d5 Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Thu, 12 Dec 2019 19:31:50 +0530 Subject: :fire: :zap: Major Update * Adds Actions, Redicers and Middlewares * Adds Http Service * Adds Cancel option for Http Service * Adds HOC's for API Loader, Sidebar and Headers * Adds Random key generator for Routes --- src/services/http.service.js | 90 +++++++++++++++++++++++++++++++++++++++++ src/services/selectors.js | 10 +++++ src/services/storage.service.js | 3 +- 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/services/selectors.js (limited to 'src/services') diff --git a/src/services/http.service.js b/src/services/http.service.js index e69de29..c3914f6 100644 --- a/src/services/http.service.js +++ b/src/services/http.service.js @@ -0,0 +1,90 @@ +import axios from 'axios'; +import Storage from './storage.service'; +import { COMMON_REQUEST, COMMON_SUCCESS, COMMON_CANCEL } from '../utils/constants'; + +class HttpServiceSingleton { + constructor() { + axios.defaults.headers.post["Content-Type"] = "application/json"; + axios.defaults.headers.put["Accept"] = "application/json"; + this.count = 0; // This will store API requests + this.complete = 0; // This will store API Success/errors + } + + set reduxStore(store) { + this.store = store; + } + + fetch(payload, noAuth) { + const cancelToken = axios.CancelToken; + this.cancelSource = cancelToken.source(); + let config = {}; + if (!noAuth) { + let token = Storage.get("token"); + config.headers = { + 'Authirization': `Bearer ${token}` + }; + } + + config.method = payload.method ? payload.method : 'get'; + config.url = payload.url ? payload.url : ''; + config.cancelToken = this.cancelSource.token; + if (payload.data) config.data = JSON.stringify(payload.data); + + return axios(config).catch((thrown) => { + if (axios.isCancel(thrown)) { + this.count = 0; + this.complete = 0; + this.store.dispatch({ + type: COMMON_CANCEL + }); + console.log('Request canceled', thrown.message); + } else { + // handle error + } + }); + } + + httpInterceptor() { + axios.interceptors.request.use((config) => { + this.count++; + this.checkApiComplete(this.store); + return config; + }, (error) => { + this.complete++; + this.checkApiComplete(this.store); + return Promise.reject(error); + }); + + axios.interceptors.response.use((response) => { + this.complete++; + this.checkApiComplete(this.store); + return response; + }, (error) => { + this.complete++; + this.checkApiComplete(this.store); + return Promise.reject(error); + }); + } + + cancelRequest() { + this.cancelSource.cancel(); + } + + //Fallback to cancel all API loaders in case of multiple API call occuts + checkApiComplete(store) { + if (this.count == this.complete) { // Cancel API loader when all requests are completed + store.dispatch({ + type: COMMON_SUCCESS + }); + } else { + store.dispatch({ + type: COMMON_REQUEST + }); + } + } +} + +const HttpService = new HttpServiceSingleton(); +// Object.freeze(HttpService); // Singleton Http Service + +export default HttpService; \ No newline at end of file diff --git a/src/services/selectors.js b/src/services/selectors.js new file mode 100644 index 0000000..f9942d4 --- /dev/null +++ b/src/services/selectors.js @@ -0,0 +1,10 @@ +import _ from "lodash"; + +export const createLoadingSelector = actions => state => { + return _(actions).some(action => _.get(state, `loading.${action}`)); +}; + +export const createNotificationSelector = actions => state => { + return _(actions) + .some(action => _.get(state, `error.${action}`)); +}; diff --git a/src/services/storage.service.js b/src/services/storage.service.js index c41d552..d29a1e5 100644 --- a/src/services/storage.service.js +++ b/src/services/storage.service.js @@ -9,7 +9,8 @@ class Storage{ if(!key||!value){ throw("Storag.set expects a 'key' and a 'value' - 'value' & 'key' can't be null"); } - localStorage.setItem(key, JSON.stringify(value)); + value = (typeof value=="string") ? value : JSON.stringify(value); + localStorage.setItem(key, value); } } -- cgit v1.2.3