Skip to content

Instantly share code, notes, and snippets.

@martynchamberlin
Created December 29, 2016 05:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martynchamberlin/904e791f250eb151e2aec09dbea2d94d to your computer and use it in GitHub Desktop.
Save martynchamberlin/904e791f250eb151e2aec09dbea2d94d to your computer and use it in GitHub Desktop.
A really squirrelly way to mock a promise library. Don't actually use this!
/**
* This is a lightweight wrapper that mimics Angular's $http service.
* The reason for this is twofold:
*
* (1) Often, two or more components will need the exact
* same resource at the same time. This should only result in
* one HTTP request but it should resolve both correctly. Angular's
* {cache: true} argument in $http.get handled this well.
*
* (2) A component will sometimes need a resource later on in a
* page state that a different component previously fetched. Except
* in cases of polling, this also results in situation in which a
* cached version must be fetched. Angular's {cache: true} also ensured this.
*
* The flags of "loading" and "resolved" in this wrapper keep the
* implementing classes from having to worry about these details, unless
* they're needed for UI feedback. The goal is that we should be able to
* make a GET call without ever having to worry about how many HTTP requests
* are being generated, while still having a guarantee that the callback will
* fulfilled as soon as the data is ready.
*
* Our usage example demonstrates that this API looks and feels just like
* the Angular service we're used to. The only difference is that unlike
* Angular's $http service, we default cache to true, not to false.
*
* ```
* import $http from '../shared/http';
*
* $http.get('some url').then((response) => {
* console.log(response);
* }).error((response) => {
* console.log(response);
* });
* ```
*/
import axios from 'axios';
const getUrls = {};
module.exports = {
get: (url, opts) => {
const defaultOptions = {
cache: true
};
const options = Object.assign({}, defaultOptions, opts);
if (!getUrls[url]) {
getUrls[url] = {
response: null,
loading: false,
resolved: false,
successCallbacks: [],
errorCallbacks: [],
};
}
if (options.cache === false ||
(getUrls[url].resolved === false && getUrls[url].loading === false)) {
getUrls[url].loading = true;
axios.get(url).then((response) => {
getUrls[url].loading = false;
getUrls[url].resolved = true;
getUrls[url].response = response;
// loop through all of our callbacks and fire them
getUrls[url].successCallbacks.map(callback => callback(response));
// reset all the callbacks
getUrls[url].callbacks = [];
}).catch((response) => {
getUrls[url].loading = false;
getUrls[url].resolved = true;
getUrls[url].errorCallbacks.map(callback => callback(response));
});
}
return {
then: (callback) => {
if (options.cache === true && getUrls[url].resolved === true) {
callback(getUrls[url].response);
} else {
// Store this callback to be called when we've resolved
getUrls[url].successCallbacks.push(callback);
}
},
error: (callback) => {
if (options.cache === true && getUrls[url].resolved === true) {
callback(getUrls[url].response);
} else {
// Store this callback to be called when we've resolved
getUrls[url].errorCallbacks.push(callback);
}
}
};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment