promise-cycle
v1.0.0
Published
A lightweight utility for controlling when promises resolve and how their results are handled.
Maintainers
Readme
promise-cycle
Let the work finish when it can. Show the result when your UI is ready.
promise-cycle gives asynchronous results a timing policy. Keep a loading indicator visible long enough to avoid a distracting flash, reveal content at the end of an animation cycle, or use a fallback while an operation is still pending.
Resolver shares one result across independently timed waits. Countdown provides reusable, stoppable countdowns for the rest of your application.
Get started · Documentation · UI recipes · API reference
Install
npm install promise-cycleTypeScript declarations, ES modules, and CommonJS exports are included. No runtime dependencies.
Quick start
Keep a loading state visible for at least 400 ms, even when the request finishes quickly:
import { Resolver } from 'promise-cycle';
await Resolver.minimum(fetch('/api/message'), 400, {
throw: false,
success: async (response) => {
const message = await response.text();
console.log(message);
},
error: (reason) => {
console.error('Could not load the message:', reason);
},
});The request starts immediately. A fast result waits for the minimum; a slow result is delivered when it arrives. See the timing diagrams.
If the request is still pending after 3 seconds, the fallback response goes through
success. Rejections go through error; throw: false prevents the original
rejection from being rethrown. The fallback is a Response to match fetch().
What you can build
| Need | Feature | Guide |
| --- | --- | --- |
| Avoid a loading indicator appearing and disappearing in a flash | minimum(ms) | Minimum visibility |
| Reveal content between repeating animation cycles | interval(firstCheck, period) | Animation timing |
| Use the result as soon as it is available | immediate() | Strategies |
| Show placeholder or cached data during a long wait | fallbackAfter and fallback | Fallbacks |
| Transform data and handle typed errors per caller | success, error, throw | Callbacks |
| Complete a wait from a user action or application event | Manual resolve() and reject() | Shared state |
| Pause and resume a timer, read time remaining, or inspect its history | Countdown | Countdown guide |
One operation, different presentation timings
import { Resolver } from 'promise-cycle';
const result = new Resolver(fetch('/api/message').then(response => response.text()));
const immediately = result.immediate();
const afterMinimum = result.minimum(400);
const onCycle = result.interval(600, 600);
await Promise.all([immediately, afterMinimum, onCycle]);Each call has its own timing and options; the request runs once. Intervals check the existing result rather than repeat the operation. Learn how shared settlement works.
Quick API
Signatures below omit generic and conditional return details. Follow the links for the full contract.
| API | Reference |
| --- | --- |
| new Resolver<Value, Reason>(source?) | Construction |
| Resolver.resolve(value?), Resolver.reject(reason?) | Static constructors |
| Resolver.immediate(source, options?) | Immediate |
| Resolver.minimum(source, minDelay, options?) | Minimum |
| Resolver.interval(source, minDelay, interval, options?) | Interval |
| resolver.immediate(options?) | Strategies |
| resolver.minimum(minDelay, options?) | Strategies |
| resolver.interval(minDelay, interval, options?) | Strategies |
| resolver.resolve(value), resolver.reject(reason) | Manual settlement |
| resolver.waiting, .status, .source | Resolver API |
| new Countdown(ms?, historySupported?) | Countdown API |
| counter.waiting, .remaining, .stop(), .resume(), .reset(ms?), .destroy() | Countdown API |
| Countdown.sleep(ms?), .normalize(value?), .isValid(value?) | Countdown API |
| Types.Options, Types.Status, Types.Source, Types.CallSource, Types.History, Types.HistoryEntry | Types |
Documentation
Start with installation and first use, choose a timing strategy, then explore practical UI recipes. The documentation home links every guide and reference page.
Timing controls result delivery; it does not cancel network requests or guarantee frame-exact rendering. See timing behavior and fallback behavior.
Project
License: MIT.
