How JavaScript’s Single Thread Handles Async and What startTransition Changes

Although JavaScript runs on a single thread, it can handle asynchronous operations through mechanisms like setTimeout, and React 18’s startTransition lets developers separate urgent UI updates from deferred work, improving responsiveness by scheduling non‑urgent tasks after urgent ones complete.

ByteFE
ByteFE
ByteFE
How JavaScript’s Single Thread Handles Async and What startTransition Changes

JavaScript single‑threaded execution model

JavaScript runs on a single call stack and a single heap. All synchronous code is executed sequentially on this stack, so only one piece of code runs at a time.

Asynchronous work with setTimeout

console.log('Javascript');
setTimeout(() => {
    console.log('Synchronous');
}, 1000);
console.log('is');

Output:

Javascript
is
undefined
Synchronous

The undefined appears because the callback passed to setTimeout is queued and executed only after the current call stack finishes. The timer does not block the stack; it schedules the callback for later.

Urgent vs. non‑urgent updates

In a typical search input the user expects:

Typed characters to appear immediately – an urgent update.

Search results to be fetched and rendered later – a non‑urgent update.

Because JavaScript is single‑threaded, a long‑running task blocks all other work until it completes, causing visible lag.

React 18 startTransition

React 18 introduces startTransition to let developers mark a piece of work as non‑urgent. Urgent updates (e.g., state that controls the UI immediately) are processed first; the transition callback runs only after all urgent work is finished.

setInputValue(value); // urgent: update input immediately
startTransition(() => {
    setSearchData(data); // non‑urgent: fetch and render results later
});

Difference from setTimeout

setTimeout

creates an asynchronous callback that runs after a timer expires, potentially reordering events. startTransition does not reorder events; it synchronously schedules the wrapped callback to run after the current urgent work, preserving the original order.

References

React 18 discussion: https://github.com/reactwg/react-18/discussions/41

Additional examples: https://github.com/reactwg/react-18/discussions/65

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScriptReactAsyncevent loopstartTransition
ByteFE
Written by

ByteFE

Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.