---
title: "Using node API for delay"
description: "Node.js has a built-in delay API. setTimeout from node:timers/promises returns a promise, so a node delay or sleep needs no callback wrapper."
canonical: https://omiid.me/notebook/39/using-node-api-for-delay
author: Omid Sayfun
published: 2025-02-06
updated: 2026-08-09
---

# Using node API for delay

A delay in Node.js is usually written as `setTimeout` wrapped in a promise. That works, and it is still the most common node delay you will find in application code:

```typescript
await new Promise((resolve) => setTimeout(resolve, 1000));
```

This snippet waits one second, then resolves to `undefined`. Node.js also ships a promise-based timer of its own, so the wrapper is not needed.

## `node:timers/promises` gives you a delay that returns a value

The built-in API lives in `node:timers/promises`. It takes the delay in milliseconds and an optional value to resolve with:

```typescript
import { setTimeout } from "node:timers/promises";

const res = await setTimeout(1000, "result");

console.log(res); // Prints 'result'
```

The call waits one second and resolves to `'result'`. The promise-wrapped `setTimeout` always resolves to `undefined`, so this version saves you a closure when the sleep has to hand a value back.

## The delay accepts `ref` and `signal` options

A third argument takes two optional settings:

```typescript
interface Options {
	ref?: boolean | undefined;
	signal?: AbortSignal | undefined;
}
```

### Set `ref` to false so the event loop can exit

By setting `ref` to `false`, the Node.js event loop can exit if there’s nothing else to do, even if the timeout is still pending. Use it for background work that should not hold the process open.

### Pass an `AbortSignal` to cancel the delay

You can pass an `AbortSignal` to cancel the timer. Abort the controller and the pending delay rejects instead of resolving, which is how you stop a wait that is no longer needed.

## tl;dr

Node.js has a built-in delay: `setTimeout` from `node:timers/promises`. It replaces the promise-wrapped `setTimeout` and adds options like `ref` and `signal` for more control over the event loop and timer cancellation.
