svelte-promisable-stores Svelte Themes

Svelte Promisable Stores

Collection of svelte stores to manage and save promises.

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, 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).

Top categories

Loading Svelte Themes