/delounce

Small library for ease async stuff – queues, delays, accumulating requests

Primary LanguageJavaScript

Delounce library

Build Status npm version Coverage Status dependencies Status code style: prettier

We all have bunch of "utility" functions in all our projects. We are pretty used to libraries like lodash, which take this burden off of us (think about functions like debounce); but modern JS applications become more and more asynchronous, and this library tries to fill this gap.

Installation

npm install --save delounce

API

Note: this library requires existing global Promise, so you might have to use native polyfill, babel-polyfill or other promises implementation, like Bluebird.

In examples we use async/await, which were standartised some time ago and available in all major browsers. However, feel free to use normal promises – each time we await something, we can safely add .then to it and write normal callback.

All time parameters take it in milliseconds (so, 1000 is equal to 1 second).

sleep

Simple function to wait some time – for tests, for imitating server response, or for polling.

import { sleep } from 'delounce';

doSome();
await sleep(2000);
doStuffAfter2Seconds();

atLeast

Function, which will execute given function and ensure that it took at least given amount of time. It might be helpful, for instance, if your server is too fast, and it creates annoying flashing; or you want to ensure that user noticed processing.

import { atLeast } from 'delounce';

// atLeast executes your code and return a promise, which will be
// resolved only after given amount of time (if passed function took less time)
// you can pass promise, function or plain value
const images = await atLeast(500, fetchImages);
// at least 500ms passed – if more, it will be resolved immediately
showImages(images);

atMost

The opposite of the previous function – we set upper limit, so it if takes longer than given amount time, we resolve promise. Also, please note that for consistency we don't resolve with anything (if it times out, with which data should we resolve?), so you should use only as an indicator of loading.

import { atMost } from 'delounce';
import { preload } from 'pic-loader';

const imgLinks = ['http://ex.com/first.jpg', 'http://ex.com/second.jpg', 'http://ex.com/third.jpg'];
// we wait one second to preload images, but if takes too much,
// we will just start to show them after one second
await atMost(1000, preload(imgLinks));
showImages(imgLinks);

limit

This function combines atLeast and atMost, executing given function, but ensuring, that it takes not more and not less than provided timing.

import { preload } from 'pic-loader';
import { limit } from 'delounce';

const imgLinks = ['http://ex.com/first.jpg', 'http://ex.com/second.jpg', 'http://ex.com/third.jpg'];
// we ensure that they will be loaded enough not to annoy with glitch, but not too long
limit({ fn: preload(imgLinks), min: 200, max: 1000 });

queue

Queues are pretty straightforward with promises (and even more with async/await) – you just chain promises with .then, or with usual code using await ... in each line. The problem is, though, that everything should be executed in one place, so all these promises know about each other. This function places promises one after another based on a name, so we can add these promises independently. For instance, we can show rows one by one, just using name rows.

import { queue } from 'delounce';

// rows will be fetched one after another
// we don't use await here, because we show rows right after loading
// but add all them synchronously
queue('rows', fetchRow(0)).then(showRow);
queue('rows', fetchRow(1)).then(showRow);
queue('rows', fetchRow(2)).then(showRow);

polling

Sometimes we execute some operation (for instance, pay bills), but there is no direct response; so we have to poll results until we get positive response. Also, sometimes we want to cancel polling, in case we left needed page, for instance.

import { polling } from 'delounce';

// will be executed after 500 / 1000 / 1500 / 2000 / etc
// checkData should return truthy value (or promise which will be
// resolved with truthy value)
// { id: 5 } – will be the first argument with which checkData
// is invoked
const { promise, cancel } = polling(500, checkData, { id: 5 });

// after returning truthy value
promise.then();

// stop polling; promise will be rejected, so you have to
// add promise.catch() to handle it
cancel();

License

MIT