The presenter describes the main thread for UIKit updates, the JavaScript thread for React Native JavaScript, and the native modules thread for native module work. Synchronous TurboModule methods such as `getItem` run on the JavaScript thread, so blocking one can make the app unresponsive. Xcode breakpoints and thread names can help identify where a method is running.
Understanding Threads and Queues in Swift TurboModules
An unnamed Callstack presenter explains how threads and dispatch queues work in Swift TurboModules for React Native on iOS.
Grand Central Dispatch lets developers submit closures to queues while the system manages its thread pool. `DispatchQueue.global().async` moves work to a background thread, and `DispatchQueue.main.async` can schedule follow-up work on the UI thread. The presenter recommends using async work in most cases because sync dispatch blocks the calling thread.
A custom dispatch queue created with only a label is serial by default, so tasks run one at a time in order. Adding the concurrent attribute lets tasks overlap: in the example, a second task runs before the first task finishes sleeping for two seconds. The presenter suggests queues for work such as file access or parallel network requests, and briefly mentions Swift actors as another option.
The presenter adds promise-based `getItemAsync` and `setItemAsync` methods, which resolve or reject instead of returning a value directly. The example moves storage work onto a custom concurrent queue and resolves the promise there; the JavaScript caller awaits the result. This avoids keeping long-running work on the shared TurboModule queue.
The presenter summarizes that native module calls begin on the TurboModule queue, while global or custom queues can handle background work. Heavy operations should not block either the main UI thread or the JavaScript thread. Send results back to those threads when their work requires them.
Takeaways
- Keep synchronous TurboModule methods short because they run on the JavaScript thread.
- Use async dispatch for background work; synchronous dispatch blocks its caller.
- Use a serial queue when tasks must run in order, and a concurrent queue when they can overlap.
- Move long-running native work to a background or custom queue, then resolve the promise with its result.
- Avoid heavy work on both the UI thread and the JavaScript thread.
Mentioned in this talk
Search inside this talk
What was claimed 7
- featureReact: Synchronous native methods run on the JavaScript thread.
“React Native calls these synchronous native methods on the JavaScript thread.”
YouTube Unverified1 source· Talk
- featureGrand Central Dispatch: Abstracts thread management by scheduling closure work on system-managed queues.
“It abstracts threads away, so we don't need to worry about creating, destroying, or managing threads ourselves.”
YouTube Unverified1 source· Talk
- featureDispatchQueue: Queues created with a label and no additional options are serial by default.
“By default, DispatchQueue with no additional options other than the label gives us a serial queue”
YouTube Unverified1 source· Talk
- featureDispatchQueue: Concurrent queues can execute tasks in parallel.
“This allows us to run tasks in parallel”
YouTube Unverified1 source· Talk
- featureTurboModules: Async methods return void and resolve or reject a promise instead of returning the value directly.
“you have to resolve the promise with the value instead of returning the value”
YouTube Unverified1 source· Talk
- featureReact: Native module methods run on the TurboModule manager queue by default.
“the default queue it’s called on is the TurboModule manager queue”
YouTube Unverified1 source· Talk
- feature
Callstack: Has a YouTube channel.“subscribing to the Callstack YouTube channel”
YouTube Unverified1 source· Talk





