Files
habitica/website/client/libs/asyncResource.js
Matteo Pagliazzi d9d7c69432 Client: async resources, make store reusable, move plugins and add getTaskFor getter (#8575)
Add library to manage async resource
Make Store reusable for easier testing
Move plugin to libs
Add getTaskFor getter with tests
2017-03-18 18:33:08 +01:00

46 lines
1.8 KiB
JavaScript

import get from 'lodash/get';
import axios from 'axios';
// Return an object used to describe, in the app state, an
// async resource loaded from the server with its data and status.
export function asyncResourceFactory () {
return {
loadingStatus: 'NOT_LOADED', // NOT_LOADED, LOADING, LOADED
data: null,
};
}
export function loadAsyncResource ({store, path, url, deserialize, forceLoad = false}) {
if (!store) throw new Error('"store" is required and must be the application store.');
if (!path) throw new Error('The path to the resource in the application state is required.');
if (!url) throw new Error('The resource\'s url on the server is required.');
if (!deserialize) throw new Error('A response deserialization function named must be passed as "deserialize".');
const resource = get(store.state, path);
if (!resource) throw new Error(`No resouce found at path "${path}".`);
const loadingStatus = resource.loadingStatus;
if (loadingStatus === 'LOADED' && !forceLoad) {
return Promise.resolve(resource);
} else if (loadingStatus === 'LOADING') {
return new Promise((resolve, reject) => {
const resourceWatcher = store.watch(state => get(state, `${path}.loadingStatus`), (newLoadingStatus) => {
resourceWatcher(); // remove the watcher
if (newLoadingStatus === 'LOADED') {
return resolve(resource);
} else {
return reject(); // TODO add reason?
}
});
});
} else if (loadingStatus === 'NOT_LOADED' || loadingStatus === 'LOADED' && forceLoad) {
return axios.get(url).then(response => { // TODO support more params
resource.loadingStatus = 'LOADED';
resource.data = deserialize(response);
return resource;
});
} else {
return Promise.reject(new Error(`Invalid loading status "${loadingStatus} for resource at "${path}".`));
}
}