npm install react-native-multithreading
npx pod-install
Requires a version of react-native-reanimated which includes my PR (2.1.0 or above).
⚠️ Warning: This is still just a proof of concept - do not use this library in production!⚠️
Since JSI is becoming more mainstream, there might be functions that are actually blocking and take a while to execute. For example, a storage library like my react-native-mmkv or an SQLite JSI library might take a few milliseconds to execute a complex call. You don't want your entire React-JS thread to freeze when doing that, since users will perceive a noticeable lag or freeze.
That's where react-native-multithreading comes in; you can simply off-load such expensive calculations/blocking calls to a separate thread with almost no overhead while your main React-JS thread can concentrate on running your app's business logic, respond to user input, update state and more. You can also run complex JS calculations such as the Fibonacci number, but that's probably a rare use-case.
Inspired by @karol-bisztyga's Multithreading PR for Reanimated
To try out the Fibonacci Example, clone the repo and run the following commands:
yarn bootstrap
cd example
yarn ios
See my tweet 🐦
To simply perform an expensive calculation on another thread without caring about the result, use the spawnThread
function:
// JS thread
spawnThread(() => {
'worklet'
// custom thread
// expensive calculation
})
// JS thread
The React-JS Thread will continue execution while the custom thread will run the given function on a custom parallel runtime.
Since spawnThread
returns a Promise
, you can also await the result. The React-JS Thread will not be blocked and will still be able to continue execution elsewhere (timers, callbacks, rendering, ...), while the custom thread runs the given function in a custom parallel runtime.
const result = await spawnThread(() => {
'worklet'
// expensive calculation
return ...
})
This example calculates the Fibonacci Number for the given input. This demonstrates expensive calculation, awaiting the result, as well as using values from "outside". (fibonacci
function and input
are captured into the new thread and therefore immutable.)
const fibonacci = (num: number): number => {
'worklet'
if (num <= 1) return 1
return fibonacci(num - 1) + fibonacci(num - 2)
}
const input = 50
const result = await spawnThread(() => {
'worklet'
console.log(`calculating fibonacci for input: ${input} in JS-Runtime: ${global._LABEL}...`)
const fib = fibonacci(input)
console.log("finished calculating fibonacci!")
return fib
})
console.log(`Fibonacci Result: ${result}`)
- You can run any JavaScript code you want in there.
- You can use variables from "outside" (e.g. state), but those will be immutable/frozen.
- You can use functions from "outside".
- Worklets (functions with the
'worklet'
directive) can be called synchronously - Normal JS functions (e.g. setState) can be called with
runOnJS
- Native JSI functions ("host functions") can be called synchronously (e.g. functions from react-native-mmkv)
- Worklets (functions with the
- You can assign Reanimated Shared Values.
- At the moment, only iOS is implemented. I'm trying to get Android working in #3 - if anyone can help me with the CMake part I'd appreciate it.
- Since the library uses JSI for synchronous native methods access, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use Flipper.
- All functions you are calling inside a custom thread, must be workletized to truly run on a separate thread. So add the
'worklet'
directive at the top of every function you're calling in that thread (including the thread callback itself), and don't forget to install the Reanimated babel plugin.
MIT
- react-native-reanimated for Shared Value adapting, essentially allowing JSI multithreading
- Erik the Coder for the Icon
- You, for appreciating my work
Note: Technically this is not multithreading, but rather multiprocessing.