Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteStart at the promise’s creation and trace every path that should make progress: calls to resolve or reject, promises returned from then or catch, values passed to await, and the underlying callback, event, timer, or request. Add breakpoints or logs at those boundaries. A promise displayed as pending at one moment may still settle later; the display alone does not prove it is stuck.
What “pending” and “resolved” mean
A promise begins pending and becomes settled when it is fulfilled or rejected. MDN defines a settled promise as one that is fulfilled or rejected, but not pending (MDN Web Docs: Promise).
As an Amazon Associate I earn from qualifying purchases.
“Resolved” is often used casually to mean “fulfilled,” but the terms are not interchangeable. When a promise’s resolve function is called with another promise or thenable, the outer promise adopts that value’s eventual state. It can therefore remain pending even though its resolve function was called. If the inner operation never settles, neither will the outer promise.
Likewise, a promise returned by a then or catch handler depends on what that handler returns. If it returns a pending promise, downstream work waits for it. Promise reactions run asynchronously through the job queue, so a pending snapshot or log taken immediately after starting work may simply be too early (MDN Web Docs: Promise.prototype.then).
#1 Best Overall
Debug it in order
- Confirm that it is actually stuck. Attach fulfillment and rejection handlers and wait for the expected operation interval. A one-time display such as
Promise { <pending> }records the state at that instant, not what the promise will do later. - Mark the boundaries. Log or set breakpoints before and after promise creation, at every
resolveandrejectcall, and at each relevant callback’s entry and exit. Include a request or operation ID if concurrent work could interleave in the console. - Audit every branch of a manually constructed promise. Inspect success, error, early-return, timeout, and cancellation paths. Each branch must eventually call
resolveorrejectif it is meant to settle. Returning a value from the promise constructor’s executor does not settle the promise; the resolve and reject functions do. - Follow every adopted or returned promise. If code calls
resolve(innerPromise), returns a promise from athenorcatchhandler, or awaits a promise, inspect that inner operation. The outer or downstream promise follows its state; it cannot force the inner work to finish. - Check the operation beneath the promise. In a callback adapter, verify the callback is invoked on success and failure. In event-driven code, confirm the listener is registered and the expected event can occur. For a request or timer, inspect whether that request or timer starts, completes, errors, or is prevented from doing so.
- Use async call stacks as a supplement. In Chrome DevTools, inspect async stack frames to look for earlier scheduling and call sites. The history shown depends on support from the framework or browser scheduling primitive, so it may not include every third-party async operation (Chrome for Developers: Console features reference; Chrome for Developers: JavaScript debugging reference).
- Try specialized runtime tracing only if simpler checks are insufficient. Node.js
async_hookscan expose async resource lifecycle information, but the Node.js documentation warns that the API has usability, safety, and performance drawbacks. If a hook needs to log, use synchronous logging: asynchronous logging can trigger more hooks and recurse (Node.js v26.10.0: Async hooks).
Common control-flow failures to look for
- A branch in a manually created promise exits without calling either settlement function.
- A callback-to-promise wrapper assumes a callback will always run, but the underlying API omits it on a particular path. Check that API’s contract as well as the callback boundary.
- The outer promise adopts an inner promise that remains pending.
- A
thenorcatchhandler returns work that never settles, leaving the downstream chain pending. - The code is being inspected too soon, before queued promise reactions have run.
- A timeout wrapper has stopped the caller from waiting, but the underlying operation is still running.
These are places to investigate, not diagnoses of a particular codebase. Without the relevant code and a reproduction, the actual missing progress point cannot be identified.
Choose the tracing method that answers the question
| Method | What it can reveal | Limit |
|---|---|---|
| Boundary logs | Which settlement branch, callback, or operation boundary was reached. | Logs show only the events you instrument; interleaved work can be confusing without operation IDs. |
| Source breakpoints | Local control flow, including whether a branch returns before settlement. | A breakpoint at the promise’s creation does not by itself reveal why an inner operation fails to progress. |
| Chrome async stacks | Earlier frames across supported asynchronous work. | Coverage depends on framework or browser primitive support; a complete trace is not guaranteed. |
Node.js async_hooks |
Async resource lifecycle events and promise-resolution events. | Node.js documents usability, safety, and performance concerns, so this is specialized instrumentation rather than the default first step. |
Node.js: interpret promiseResolve carefully
Node’s promiseResolve hook runs when the promise constructor’s resolve function is invoked. That event does not prove that the promise is fulfilled: if resolution adopts another pending promise, the outer promise still waits for the adopted value. Use the hook as one lifecycle signal, not as a final-state verdict (Node.js v26.10.0: Async hooks).
Rank #2
For routine debugging, begin with source breakpoints and boundary logs. Reach for async_hooks only when lifecycle information is needed and the simpler view is not enough.
Recommended Free Tools
Use timeouts without mistaking them for cancellation
A timeout can bound how long a caller waits and let it report a timeout, for example by racing the operation against a timer. But Promise.race() does not cancel the losing operation. While a pending input remains pending and reachable, it can retain handlers attached by the race.
JavaScript promises do not provide a first-class cancellation protocol. If the operation is no longer useful, cancel it through the underlying API when supported—often with an AbortController and its AbortSignal. Check that API’s cancellation behavior rather than assuming that timing out a promise stops the work (MDN Web Docs: Promise.race; MDN Web Docs: AbortSignal).
Quick Recap
Best Value
Rank #4
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




