npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

async-wait-until

v2.0.31

Published

Waits until the given predicate function returns a truthy value, then resolves

Downloads

478,290

Readme

async-wait-until

A lightweight, zero-dependency library for waiting asynchronously until a specific condition is met. Works in any JavaScript environment that supports Promises, including older Node.js versions and browsers (with polyfills if necessary).

npm version npm downloads MIT License 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

📖 Detailed Documentation

For detailed documentation, visit https://devlato.github.io/async-wait-until/


🚀 Installation

Install using npm:

npm install async-wait-until

The library includes UMD and ESM bundles (plus additional formats), so you can use it in any environment.

import { waitUntil } from 'async-wait-until';

// Example: Wait for an element to appear
await waitUntil(() => document.querySelector('#target') !== null);

🛠️ How to Use

Basic Example: Wait for a DOM Element

import { waitUntil } from 'async-wait-until';

const waitForElement = async () => {
  // Wait for an element with the ID "target" to appear
  const element = await waitUntil(() => document.querySelector('#target'), { timeout: 5000 });
  console.log('Element found:', element);
};

waitForElement();

Handling Timeouts

If the condition is not met within the timeout, a TimeoutError is thrown.

import { waitUntil, TimeoutError } from 'async-wait-until';

const waitForElement = async () => {
  try {
    const element = await waitUntil(() => document.querySelector('#target'), { timeout: 5000 });
    console.log('Element found:', element);
  } catch (error) {
    if (error instanceof TimeoutError) {
      console.error('Timeout: Element not found');
    } else {
      console.error('Unexpected error:', error);
    }
  }
};

waitForElement();

📚 API Reference

waitUntil(predicate, options)

Waits for the predicate function to return a truthy value and resolves with that value.

Parameters:

| Name | Type | Required | Default | Description | | --------------------------------- | ---------- | -------- | --------- | ------------------------------------------------------------------------------------ | | predicate | Function | ✅ Yes | - | A function that returns a truthy value (or a Promise for one). | | 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

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

// Async predicate example
const checkApiStatus = async (): Promise<boolean> => {
  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

import { Options } from 'async-wait-until';

const customOptions: Options = {
  timeout: 15000,
  intervalBetweenAttempts: 200
};

await waitUntil(() => someCondition(), customOptions);

💡 Recipes

Wait Indefinitely

Use WAIT_FOREVER to wait without a timeout:

import { waitUntil, WAIT_FOREVER } from 'async-wait-until';

await waitUntil(() => someCondition, { timeout: WAIT_FOREVER });

Adjust Retry Interval

Change how often the predicate is evaluated:

await waitUntil(() => someCondition, { intervalBetweenAttempts: 1000 }); // Check every 1 second

Wait for API Response

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)

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

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

// 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

<!-- UMD bundle via CDN -->
<script src="https://unpkg.com/async-wait-until@latest/dist/index.js"></script>
<script>
  // Available as global variable
  asyncWaitUntil.waitUntil(() => document.querySelector('#target'))
    .then(element => console.log('Found:', element));
</script>

ES Modules in Browser

<script type="module">
  import { waitUntil } from 'https://unpkg.com/async-wait-until@latest/dist/index.esm.js';
  
  const element = await waitUntil(() => document.querySelector('#target'));
  console.log('Found:', element);
</script>

🔍 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:

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

Contributions are welcome! To contribute:

  1. Fork and clone the repository.
  2. Install dependencies: npm install.
  3. Use the following commands:
  • Run Tests: npm test
  • Lint Code: npm run lint
  • Format Code: npm run format
  • Build Library: npm run build
  • Generate Docs: npm run docs

📝 Links