This project contains a collection of stores to manage and save promises.
It's mostly used together with svelte's await blocks.
If you're using it to fetch data from a backend API, try using axios, since fetch does not trigger catch for 4xx/5xx responses.
npm install --save-dev svelte-promisable-stores
Note: we recommend using --save-dev instead of --save to enable better SSR support (mostly for Sapper).
On Svelte's REPL:
promisable// stores.js
import axios from 'axios';
import { promisable } from 'svelte-promisable-stores';
// promiseFunction: function that returns a promise
const fetchPerson = (personId) =>
axios
.get(`//jsonplaceholder.typicode.com/users/${personId}`)
.then((response) => response.data);
export const currentPerson = promisable(
fetchPerson,
// shouldRefreshPromise: function that evaluates if
// promise should be refreshed when `dispatch` is called.
// In this case, it fetches a person's data
// if there is no data for the store or
// if it's id is different from the one passed to `dispatch`.
(currentStateData, personId) =>
!currentStateData || personId != currentStateData.id
);
<!-- Person.svelte -->
<script>
import { onMount } from 'svelte';
import { currentPerson } from './stores';
export let personId;
onMount(() => {
currentPerson.dispatch(personId);
});
</script>
{#if $currentPerson}
{#await $currentPerson}
<p>Loading...</p>
{:then $currentPerson}
<dl>
{#each $currentPerson as person}
<dt>Name:</dt>
<dd>{person.name}</dd>
<dt>Email:</dt>
<dd>{person.email}</dd>
{/each}
</dl>
{:catch $currentPerson}
<h1>Person not found</h1>
{/await}
{/if}
derivedPromisable// stores.js
import axios from 'axios';
import { writable } from 'svelte/store';
import { derivedPromisable } from 'svelte-promisable-stores';
export const searchTerm = writable('');
const fetchPeopleByName = ($searchTerm) =>
axios
.get(`//jsonplaceholder.typicode.com/users?q=${$searchTerm}`)
.then((response) => response.data);
export const people = derivedPromisable(
searchTerm, // <- store to derive data from
fetchPeopleByName, // <- function that returns a promise
// shouldRefreshPromise: same as the `promisable` one
(currentStateData, $searchTerm, previousSearchTerm) =>
$searchTerm && $searchTerm !== previousSearchTerm
);
<!-- SearchPeopleByName.svelte -->
<script>
import {searchTerm, people} from './store';
let timer;
// debouncing is always a good idea :]
function handleKeyup(value){
clearTimeout(timer);
timer = setTimeout(() => searchTerm.set(value), 500);
}
</script>
<div>
<input type="text" value={$searchTerm} on:keyup={e => handleKeyup(e.target.value)} />
</div>
{#if $searchTerm}
{#await $people}
<p>Searching...</p>
{:then $people}
{#each $people as person}
<a rel="preload" href="/person/{person.id}">
<h1>Name: {person.name}</h1>
</a>
{/each}
{:catch $people}
<h1>ohno, something wrong isn't right! here's ther error:</h1>
<p>{JSON.stringify($people)}</p>
{/await}
{/if}
promisable(promiseFunction: function, shouldRefreshPromise = () => true):Extended writable stores.
Receives:
promiseFunction: required, returns Promise. It expects a function that returns a promise (for example, a fetch or axios call);shouldRefreshPromise: optional, returns Boolean. It receives multiple arguments. The first is always the current data from its own resolved/rejected promise. The others are all the arguments passed to the dispatch method.Returns:
subscribe, set, update: directly from the embedded writable store;dispatch: this method calls the provided promiseFunction passing any arguments and saves inside the store its returned promise. If a shouldRefreshPromise function was provided, dispatch calls it before promiseFunction and, if it returns false, promiseFunction will not be called and the promisable store data won't change;isPromisable: always set to true. Only used internally on derivedPromisable stores, for a better developer experience (no .thens inside shouldRefreshPromise).derivedPromisable(store, promiseFunction: function, shouldRefreshPromise = () => true):Extended derived stores.
Receives:
store: any svelte store, including promisables;promiseFunction: required, returns Promise. It expects a function that returns a promise (for example, a fetch or axios call). promiseFunction is called with the provided store's data, whenever its data changes;shouldRefreshPromise: optional, returns Boolean. It receives multiple arguments. The first is always the current data from its own resolved/rejected promise. The others are all the arguments passed to the dispatch method.Returns:
subscribe: directly from the embedded derived store;isPromisable: always set to true. Only used internally on derivedPromisable stores, for a better developer experience (no .thens inside shouldRefreshPromise).