mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Add library to manage async resource Make Store reusable for easier testing Move plugin to libs Add getTaskFor getter with tests
46 lines
1.8 KiB
JavaScript
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}".`));
|
|
}
|
|
}
|