Skip to content

Instantly share code, notes, and snippets.

@jeongtae
Last active May 30, 2023 04:49
Show Gist options
  • Save jeongtae/4f001ad1e632ffaadcaf2ce514f378d6 to your computer and use it in GitHub Desktop.
Save jeongtae/4f001ad1e632ffaadcaf2ce514f378d6 to your computer and use it in GitHub Desktop.
[Vue composable] useFetcher
import { ref } from 'vue';
const CacheMap = new Map<string, QuerablePromise<any>>();
export function useFetcher<T>(key: string, fetcherFn: () => Promise<T>) {
const data = ref<T | null>(null);
const error = ref<any | null>(null);
let cache = CacheMap.get(key);
if (cache === undefined) {
cache = MakeQuerablePromise(fetcherFn());
CacheMap.set(key, cache);
}
if (cache.isFulfilled) {
data.value = cache.fulfilledValue;
} else if (cache.isRejected) {
error.value = cache.rejectedError;
} else {
cache
.then((newData) => {
data.value = newData;
})
.catch((newError) => {
error.value = newError;
});
}
return { data, error };
}
type QuerablePromise<T> = Promise<T> &
(
| {
isFulfilled: false;
isRejected: false;
fulfilledValue: null;
rejectedError: null;
}
| {
isFulfilled: false;
isRejected: true;
fulfilledValue: null;
rejectedError: any | null;
}
| {
isFulfilled: true;
isRejected: false;
fulfilledValue: T | null;
rejectedError: null;
}
);
/**
* This function allow you to modify a JS Promise by adding some status properties.
* Based on: http://stackoverflow.com/questions/21485545/is-there-a-way-to-tell-if-an-es6-promise-is-fulfilled-rejected-resolved
* But modified according to the specs of promises : https://promisesaplus.com/
*/
function MakeQuerablePromise<T>(promise: Promise<T>): QuerablePromise<T> {
// Set initial state
let isFulfilled = false;
let fulfilledValue: T | null;
let isRejected = false;
let rejectedError: any | null;
// Observe the promise, saving the fulfillment in a closure scope.
const result = promise
.then((v) => {
isFulfilled = true;
fulfilledValue = v;
return v;
})
.catch((e) => {
isRejected = true;
rejectedError = e;
throw e;
});
return Object.assign(result, {
get isFulfilled() {
return isFulfilled;
},
get fulfilledValue() {
return fulfilledValue;
},
get isRejected() {
return isRejected;
},
get rejectedError() {
return rejectedError;
},
}) as QuerablePromise<T>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment