In Dart, what happens when code that calls Isolate.run or Isolate.spawn is compiled for the web, and what are the alternatives?
answer
- native platforms only
- UnsupportedError at run time
- web workers are separate programs
- keep work async and chunked
- hide the choice behind one API
basics
~20 sThe Dart web platform does not implement isolates: under the JavaScript compiler, calls such as Isolate.spawn throw UnsupportedError. Web code must run the work on the main thread, split into chunks, or move it into a separately compiled web worker.
solid answer
~40 sOnly Dart's native platform — the VM and AOT-compiled apps — implements isolates. When compiled to JavaScript, `dart:isolate`'s spawning APIs are stubs: `Isolate.spawn` throws `UnsupportedError`, and `Isolate.run` fails too, because it throws while creating its result port before it can spawn. So shared code that offloads work must branch by platform: on native, use `Isolate.run`; on the web, either run the work on the main thread — ideally split into chunks separated by `await`s so the page stays responsive — or move it into a **web worker**, which is a separately compiled program started much like `Isolate.spawnUri`, communicating by copying messages. Hide the choice behind one async function, selected with a conditional import or a platform check, so callers do not care. Flutter's own `compute()` wrapper and its web behaviour are a separate topic.
code
dart · 18 lines// checksum_background.dart
export 'checksum_background_web.dart'
if (dart.library.io) 'checksum_background_native.dart';
// checksum_background_native.dart
import 'dart:isolate';
import 'dart:typed_data';
import 'checksum.dart';
Future<int> checksumInBackground(Uint8List bytes) =>
Isolate.run(() => checksum(bytes));
// checksum_background_web.dart
import 'dart:typed_data';
import 'checksum.dart';
// No isolates on the web: compute directly (or chunk, or use a worker).
Future<int> checksumInBackground(Uint8List bytes) async => checksum(bytes);go deeper
Remember that isolates exist only on native platforms, not in web builds.
Explain that the web runtime stubs spawning APIs to throw UnsupportedError at run time, and list the main-thread, chunking and web-worker alternatives.
Design shared code with one async API and conditional imports, and test the web path explicitly so a missing isolate is not discovered in production.
Decide whether heavy client work belongs on the web client at all, on a worker, or on a server, given the web platform's lack of isolates.
## What the web platform lacks Dart has two platform families: **native** (the Dart VM for command-line and server code, plus AOT-compiled mobile and desktop apps) and **web** (compiled to JavaScript or WebAssembly). dart.dev states it plainly: only the Dart Native platform implements isolates. The `dart:isolate` library still exists for web compilation, but its spawning surface is stubbed out. In the SDK's JavaScript runtime patch: - `Isolate.spawn` and `Isolate.spawnUri` throw `UnsupportedError`; - constructing a `RawReceivePort` throws `UnsupportedError`; - `Isolate.current`, `Isolate.debugName` and similar members throw as well. `Isolate.run` is written in terms of those pieces — it creates a `RawReceivePort` and then calls `Isolate.spawn` — so on the web it throws before any work happens. The failure is at **run time**, not compile time, which is why it tends to surface only when someone first tries the web build. ## Alternatives on the web | Option | How it works | Trade-off | |---|---|---| | Run on the main thread | Call the function directly | Simple; blocks the page while it runs | | Chunk the work | Process a slice, `await` a zero-duration delay, repeat | Page stays responsive; total time grows; still one thread | | Web worker | A separately compiled Dart (or JS) program running in a background thread, messaged with `postMessage` | Real parallelism; separate entry point and build step; data is copied | | Do it on a server | Send the input to a backend | Moves the cost off the device; needs network and a service | dart.dev compares a web worker to `Isolate.spawnUri`: you must declare a separate program entry point and compile it separately, and there is no equivalent of `Isolate.spawn` that reuses the running program's code. ## Writing shared code that works everywhere For a package or app that targets both native and web — say the checksum logic of a backup tool that also has a browser-based restore page: 1. Keep the **pure computation** — `checksum(bytes)` — in a platform-neutral library. 2. Expose one async function, `Future<int> checksumInBackground(Uint8List bytes)`. 3. Provide two implementations and pick one with a **conditional import** keyed on `dart.library.io` or `dart.library.js_interop`: the native one calls `Isolate.run`, the web one runs the checksum directly (or in chunks, or via a worker). 4. Test both builds; a unit test on the VM will never exercise the web path. ## What does not change - `async`/`await`, `Future` and `Stream` work the same on every platform; they provide waiting without blocking, not parallelism. - The web's main thread has one event loop, just like a single isolate, so the same rule applies: long synchronous work freezes everything until it finishes.
- Does a Dart web build fail to compile if it imports dart:isolate?Not necessarily: the library is present for web compilation, but its spawning members are stubs that throw `UnsupportedError` when called. The problem therefore appears at run time, on the first call to `Isolate.run` or `Isolate.spawn`, which is why the web path needs its own tests.
- Why is splitting work into chunks with awaits not the same as using an isolate?Chunking only lets the single event loop handle other events between slices, so the page stays responsive. All slices still run on the same thread, one after another, so the total time does not shrink and no second core is used.
saying these in an interview costs you the question
- Isolate.run transparently becomes a web worker on the web.
- The web compiler rejects any import of dart:isolate.
- async code runs in parallel on the web instead of isolates.
- A web worker can be started from a closure like Isolate.spawn.
- Isolate.run on the web runs the function on the main thread instead.