diff --git a/README.md b/README.md index 2461855..5673371 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,28 @@ A lightweight, zero-dependency library for waiting asynchronously until a specif ![MIT License](https://img.shields.io/npm/l/async-wait-until) [![Maintainability](https://api.codeclimate.com/v1/badges/2a967399786c0d306247/maintainability)](https://codeclimate.com/github/devlato/async-wait-until/maintainability) +## โœจ Features + +- ๐Ÿš€ **Zero dependencies** - Lightweight and fast +- ๐Ÿ”ง **TypeScript support** - Full TypeScript definitions included +- ๐ŸŒ **Universal compatibility** - Works in Node.js and browsers +- โšก **Flexible configuration** - Customizable timeouts and intervals +- ๐ŸŽฏ **Promise-based** - Clean async/await syntax +- ๐Ÿ“ฆ **Multiple formats** - UMD, ESM, and additional format bundles +- ๐Ÿ›ก๏ธ **Error handling** - Built-in timeout error handling + +## ๐Ÿ“š Table of Contents + +- [Installation](#-installation) +- [How to Use](#๏ธ-how-to-use) +- [API Reference](#-api) +- [TypeScript Usage](#-typescript-usage) +- [Recipes](#-recipes) +- [Browser Compatibility](#-browser-compatibility) +- [Troubleshooting](#-troubleshooting) +- [Development and Testing](#-development-and-testing) +- [Links](#-links) + ## ๐Ÿ“– Detailed Documentation For detailed documentation, visit [https://devlato.github.io/async-wait-until/](https://devlato.github.io/async-wait-until/) @@ -21,7 +43,7 @@ Install using npm: npm install async-wait-until ``` -The library includes UMD, CommonJS, and ESM bundles, so you can use it in any environment. +The library includes UMD and ESM bundles (plus additional formats), so you can use it in any environment. ```javascript import { waitUntil } from 'async-wait-until'; @@ -73,7 +95,7 @@ waitForElement(); --- -## ๐Ÿ“š API +## ๐Ÿ“š API Reference ### `waitUntil(predicate, options)` @@ -87,6 +109,75 @@ Waits for the `predicate` function to return a truthy value and resolves with th | `options.timeout` | `number` | ๐Ÿšซ No | `5000` ms | Maximum wait time before throwing `TimeoutError`. Use `WAIT_FOREVER` for no timeout. | | `options.intervalBetweenAttempts` | `number` | ๐Ÿšซ No | `50` ms | Interval between predicate evaluations. | +### Exported Constants + +| Name | Value | Description | +| --------------------------------------- | ----- | ---------------------------------------------- | +| `WAIT_FOREVER` | `โˆž` | Use for infinite timeout (no time limit). | +| `DEFAULT_TIMEOUT_IN_MS` | `5000`| Default timeout duration in milliseconds. | +| `DEFAULT_INTERVAL_BETWEEN_ATTEMPTS_IN_MS`| `50` | Default interval between attempts in milliseconds. | + +### Exported Classes + +- **`TimeoutError`** - Error thrown when timeout is reached before condition is met. + +--- + +## ๐Ÿ”ง TypeScript Usage + +This library is written in TypeScript and includes full type definitions. Here are some TypeScript-specific examples: + +### Basic TypeScript Usage + +```typescript +import { waitUntil, TimeoutError, WAIT_FOREVER } from 'async-wait-until'; + +// The return type is automatically inferred +const element = await waitUntil(() => document.querySelector('#target')); +// element is typed as Element | null + +// With custom timeout and interval +const result = await waitUntil( + () => someAsyncCondition(), + { + timeout: 10000, + intervalBetweenAttempts: 100 + } +); +``` + +### Using with Async Predicates + +```typescript +// Async predicate example +const checkApiStatus = async (): Promise => { + const response = await fetch('/api/health'); + return response.ok; +}; + +try { + await waitUntil(checkApiStatus, { timeout: 30000 }); + console.log('API is ready!'); +} catch (error) { + if (error instanceof TimeoutError) { + console.error('API failed to become ready within 30 seconds'); + } +} +``` + +### Type-Safe Options + +```typescript +import { Options } from 'async-wait-until'; + +const customOptions: Options = { + timeout: 15000, + intervalBetweenAttempts: 200 +}; + +await waitUntil(() => someCondition(), customOptions); +``` + --- ## ๐Ÿ’ก Recipes @@ -109,6 +200,152 @@ Change how often the predicate is evaluated: await waitUntil(() => someCondition, { intervalBetweenAttempts: 1000 }); // Check every 1 second ``` +### Wait for API Response + +```javascript +const waitForApi = async () => { + const response = await waitUntil(async () => { + try { + const res = await fetch('/api/status'); + return res.ok ? res : null; + } catch { + return null; // Keep trying on network errors + } + }, { timeout: 30000, intervalBetweenAttempts: 1000 }); + + return response.json(); +}; +``` + +### Wait for File System Changes (Node.js) + +```javascript +import fs from 'fs'; +import { waitUntil } from 'async-wait-until'; + +// Wait for a file to be created +const filePath = './important-file.txt'; +await waitUntil(() => fs.existsSync(filePath), { timeout: 10000 }); + +// Wait for file to have content +await waitUntil(() => { + if (fs.existsSync(filePath)) { + return fs.readFileSync(filePath, 'utf8').trim().length > 0; + } + return false; +}); +``` + +### Wait for Database Connection + +```javascript +const waitForDatabase = async (db) => { + await waitUntil(async () => { + try { + await db.ping(); + return true; + } catch { + return false; + } + }, { timeout: 60000, intervalBetweenAttempts: 2000 }); + + console.log('Database is ready!'); +}; +``` + +### Wait with Custom Conditions + +```javascript +// Wait for multiple conditions +const waitForComplexCondition = async () => { + return waitUntil(() => { + const user = getCurrentUser(); + const permissions = getPermissions(); + const apiReady = isApiReady(); + + // All conditions must be true + return user && permissions.length > 0 && apiReady; + }); +}; + +// Wait for specific value ranges +const waitForTemperature = async () => { + return waitUntil(async () => { + const temp = await getSensorTemperature(); + return temp >= 20 && temp <= 25 ? temp : null; + }); +}; +``` + +--- + +## ๐ŸŒ Browser Compatibility + +This library works in any JavaScript environment that supports Promises: + +**Node.js:** โœ… Version 0.14.0 and above +**Modern Browsers:** โœ… Chrome 32+, Firefox 29+, Safari 8+, Edge 12+ +**Legacy Browsers:** โœ… With Promise polyfill (e.g., es6-promise) + +### CDN Usage + +```html + + + +``` + +### ES Modules in Browser + +```html + +``` + +--- + +## ๐Ÿ” Troubleshooting + +### Common Issues + +**Q: My predicate never resolves, what's wrong?** +A: Make sure your predicate function returns a truthy value when the condition is met. Common mistakes: +- Forgetting to return a value: `() => { someCheck(); }` โŒ +- Correct: `() => { return someCheck(); }` โœ… or `() => someCheck()` โœ… + +**Q: I'm getting unexpected timeout errors** +A: Check that: +- Your timeout is long enough for the condition to be met +- Your predicate function doesn't throw unhandled errors +- Network requests in predicates have proper error handling + +**Q: The function seems to run forever** +A: This happens when: +- Using `WAIT_FOREVER` without proper condition logic +- Predicate always returns falsy values +- Add logging to debug: `() => { const result = myCheck(); console.log(result); return result; }` + +**Q: TypeScript compilation errors** +A: Ensure you're importing types correctly: +```typescript +import { waitUntil, Options, TimeoutError } from 'async-wait-until'; +``` + +### Performance Tips + +- Use reasonable intervals (50-1000ms) to balance responsiveness and CPU usage +- For expensive operations, increase the interval: `{ intervalBetweenAttempts: 1000 }` +- Implement proper error handling in async predicates to avoid unnecessary retries +- Consider using `WAIT_FOREVER` with external cancellation for long-running waits + --- ## ๐Ÿงช Development and Testing diff --git a/package.json b/package.json index f8aab4b..e48d2bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "async-wait-until", - "version": "2.0.29", + "version": "2.0.30", "description": "Waits until the given predicate function returns a truthy value, then resolves", "main": "./dist/index.js", "module": "./dist/index.esm.js",