JavaScript
Promises
setTimeout
Asynchronous Programming
Function Arguments

passing multiple arguments to promise resolution within setTimeout

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When using Promises with setTimeout, developers sometimes try to pass multiple values to resolve as separate arguments. A Promise resolves to one value only, so extra arguments are ignored. The correct pattern is to wrap multiple outputs in one container such as an object or array.

Promise Resolution Rules

The Promise resolve function accepts a single value. That value can be a primitive, object, array, or another promise.

If you do this:

javascript
resolve("ok", 200, "extra")

only the first value is used. This often causes subtle bugs when callers expect all values.

Correct Pattern: Resolve an Object

Objects are usually the clearest option because keys describe meaning.

javascript
1function delayedUser() {
2  return new Promise((resolve) => {
3    setTimeout(() => {
4      resolve({ id: 7, name: "Ivy", status: "active" });
5    }, 300);
6  });
7}
8
9(async () => {
10  const result = await delayedUser();
11  console.log(result.id, result.name, result.status);
12})();

This keeps caller code readable and resilient to future field additions.

Alternative Pattern: Resolve an Array Tuple

If order is stable and compactness matters, return an array and destructure it.

javascript
1function delayedResponse() {
2  return new Promise((resolve) => {
3    setTimeout(() => {
4      resolve(["ok", 200, Date.now()]);
5    }, 200);
6  });
7}
8
9(async () => {
10  const [message, code, timestamp] = await delayedResponse();
11  console.log(message, code, timestamp);
12})();

This works well, but object returns are usually easier for long-term maintenance.

Handling Success and Failure with Structured Data

For robust async APIs, return a predictable shape and reject errors explicitly.

javascript
1function delayedTask(shouldFail = false) {
2  return new Promise((resolve, reject) => {
3    setTimeout(() => {
4      if (shouldFail) {
5        reject(new Error("Task failed"));
6        return;
7      }
8      resolve({ ok: true, value: 42, source: "timer" });
9    }, 250);
10  });
11}
12
13(async () => {
14  try {
15    const res = await delayedTask(false);
16    console.log(res.ok, res.value);
17  } catch (err) {
18    console.error(err.message);
19  }
20})();

Keeping structured success payloads and explicit rejection paths reduces caller ambiguity.

Timeouts with External Data and Cancellation

In real applications, setTimeout wrappers are often used for simulated latency or timeout protection. If function is cancellable, design API to communicate cancellation state consistently.

A simple pattern is to resolve object with cancelled flag when cancel path is expected, and reserve rejection for true errors.

javascript
1function delayedWithCancel(signal) {
2  return new Promise((resolve, reject) => {
3    const id = setTimeout(() => resolve({ cancelled: false, data: "done" }), 500);
4
5    signal.addEventListener("abort", () => {
6      clearTimeout(id);
7      resolve({ cancelled: true, data: null });
8    }, { once: true });
9  });
10}

This avoids treating cancellation as exceptional failure in caller logic.

Testing Multi-Value Promise APIs

Unit tests should validate exact payload shape, not only truthy values.

Example assertions to include:

  • resolved type is object or array as designed
  • required fields exist
  • timeout path and reject path behave consistently

If team uses TypeScript, define return types explicitly to prevent mismatch between implementation and caller expectations.

TypeScript Contract Example

When using TypeScript, returning a named payload interface helps callers avoid positional mistakes and keeps refactors safe.

typescript
type DelayedResult = { message: string; code: number };

Common Pitfalls

  • Passing multiple positional arguments to resolve and expecting all of them.
  • Returning ambiguous arrays without clear ordering contract.
  • Mixing cancellation, success, and error into inconsistent payload shapes.
  • Rejecting expected business states that should be normal resolved outcomes.
  • Skipping tests for delayed timing and failure branch behavior.

Summary

  • Promise resolution returns one value, not multiple separate arguments.
  • Wrap multiple outputs in an object or array.
  • Prefer object payloads for readability and future compatibility.
  • Keep success, failure, and cancellation contracts explicit.
  • Test payload shape and branch behavior to avoid async integration bugs.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.