Improve implementation of asyncRefresh

This commit is contained in:
Henrik Giesel 2021-03-21 21:07:35 +01:00
parent a9c16a3cd8
commit 75a8b7d318
3 changed files with 67 additions and 34 deletions

View file

@ -1,28 +1,30 @@
import { Readable, readable, derived } from "svelte/store"; import { Readable, readable, derived } from "svelte/store";
export interface AsyncData<T, E> { export interface AsyncData<T, E> {
value: Readable<T | null>, value: Readable<T | null>;
error: Readable<E | null>, error: Readable<E | null>;
pending: Readable<boolean>, pending: Readable<boolean>;
success: Readable<boolean>, success: Readable<boolean>;
} }
function useAsync<T, E = unknown>(asyncFunction: () => Promise<T>): AsyncData<T, E> { function useAsync<T, E = unknown>(asyncFunction: () => Promise<T>): AsyncData<T, E> {
const promise = asyncFunction(); const promise = asyncFunction();
const value = readable(null, (set: (value: T) => void) => { const value = readable(null, (set: (value: T) => void) => {
promise.then((value: T) => set(value)) promise.then((value: T) => set(value));
}) });
const error = readable(null, (set: (value: E) => void) => { const error = readable(null, (set: (value: E) => void) => {
promise.catch((value: E) => set(value)) promise.catch((value: E) => set(value));
}) });
const pending = derived([value, error], (_, set) => set(false), true) const pending = readable(true, (set: (value: boolean) => void) => {
const success= derived([value], (_, set) => set(true), false) promise.finally(() => set(false));
});
return { value, error, pending, success } const success = derived([value], (_, set) => set(true), false);
return { value, error, pending, success };
} }
export default useAsync export default useAsync;

View file

@ -1,30 +1,61 @@
import { Readable, derived, get } from "svelte/store"; import { Readable, readable, derived } from "svelte/store";
import useAsync, { AsyncData } from "./async";
interface AsyncRefreshData<T, E> { interface AsyncRefreshData<T, E> {
value: Readable<T | null>, value: Readable<T | null>;
error: Readable<E | null>, error: Readable<E | null>;
pending: Readable<boolean>, pending: Readable<boolean>;
success: Readable<boolean>, success: Readable<boolean>;
loading: Readable<boolean>, loading: Readable<boolean>;
} }
function useAsyncRefresh<T, E>(
asyncFunction: () => Promise<T>,
dependencies: [Readable<unknown>, ...Readable<unknown>[]]
): AsyncRefreshData<T, E> {
const initial = asyncFunction();
const promise = derived(dependencies, (_, set) => set(asyncFunction()), initial);
function useAsyncRefresh<T, E = unknown>(asyncFunction: () => Promise<T>, dependencies: [Readable<unknown>, ...Readable<unknown>[]]): AsyncRefreshData<T, E> { const value = derived(
const current = derived( promise,
dependencies, ($promise, set: (value: T | null) => void) => {
(_, set: (value: AsyncData<T, E>) => void) => set(useAsync<T, E>(asyncFunction)), $promise.then((value: T) => set(value));
useAsync<T, E>(asyncFunction), return () => set(null);
) },
null
);
const value = derived(current, ($current, set: (value: T | null) => void) => set(get($current.value)), null) const error = derived(
const error = derived(current, ($current, set: (error: E | null) => void) => set(get($current.error)), null) promise,
($promise, set: (error: E | null) => void) => {
$promise.catch((error: E) => set(error));
return () => set(null);
},
null
);
const pending = derived(current, (_, set) => set(false), true) const pending = readable(true, (set: (value: boolean) => void) => {
const success = derived(current, ($current, set: (success: boolean) => void) => set(get($current.success)), false) initial.finally(() => set(false));
const loading = derived(current, ($current, set: (pending: boolean) => void) => set(get($current.pending)), true) });
return { value, error, pending, success, loading } const loading = derived(
[value, error],
(_, set) => {
set(false);
return () => set(true);
},
true
);
const success = derived(
[value],
(_, set) => {
set(true);
return () => set(false);
},
false
);
return { value, error, pending, loading, success };
} }
export default useAsyncRefresh export default useAsyncRefresh;

View file

@ -3,7 +3,7 @@
"compilerOptions": { "compilerOptions": {
"target": "es6", "target": "es6",
"module": "es6", "module": "es6",
"lib": ["es2017", "es2019.array", "dom", "dom.iterable"], "lib": ["es2017", "es2019.array", "es2018.promise", "dom", "dom.iterable"],
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"anki/*": ["../bazel-bin/ts/lib/*"] "anki/*": ["../bazel-bin/ts/lib/*"]