svelte-promisable-stores
v0.1.3
Published
Svelte stores to manage and save promises/API calls.
Downloads
99
Maintainers
Readme
svelte-promisable-stores
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.
Installing
npm install --save-dev svelte-promisable-stores
Note: we recommend using --save-dev
instead of --save
to enable better SSR support (mostly for Sapper).
Examples
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}
API
promisable(promiseFunction: function, shouldRefreshPromise = () => true)
:
Extended writable
stores.
Receives:
promiseFunction
: required, returnsPromise
. It expects a function that returns a promise (for example, a fetch or axios call);shouldRefreshPromise
: optional, returnsBoolean
. 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 thedispatch
method.
Returns:
subscribe, set, update
: directly from the embeddedwritable
store;dispatch
: this method calls the providedpromiseFunction
passing any arguments and saves inside the store its returned promise. If ashouldRefreshPromise
function was provided,dispatch
calls it beforepromiseFunction
and, if it returns false,promiseFunction
will not be called and thepromisable
store data won't change;isPromisable
: always set totrue
. Only used internally onderivedPromisable
stores, for a better developer experience (no.then
s insideshouldRefreshPromise
).
derivedPromisable(store, promiseFunction: function, shouldRefreshPromise = () => true)
:
Extended derived
stores.
Receives:
store
: any svelte store, includingpromisable
s;promiseFunction
: required, returnsPromise
. 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, returnsBoolean
. 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 thedispatch
method.
Returns:
subscribe
: directly from the embeddedderived
store;isPromisable
: always set totrue
. Only used internally onderivedPromisable
stores, for a better developer experience (no.then
s insideshouldRefreshPromise
).