Async Callbacks, Promises, and Events from Native
Return data from native code using Promises and RCTPromiseResolveBlock, send events to JavaScript with RCTEventEmitter, and handle them in JS with NativeEventEmitter.
Why Native Methods Must Be Async
React Native native module methods run on a native background thread, not the JavaScript thread. Because the two runtimes run independently, native code cannot return a value directly. Instead it must communicate results back to JavaScript through one of three patterns: Callbacks, Promises, or Events. Each pattern suits different use cases based on how many responses you need and when they arrive.
Callbacks: The Original Pattern
Callbacks are JavaScript functions passed as arguments to a native method. The native code stores them and invokes them later. The convention is to pass two callbacks — one for success and one for failure — similar to Node.js error-first callbacks. A callback can only be invoked once; invoking it twice throws a runtime error on the JS side.
// Kotlin
@ReactMethod
fun readFile(
path: String,
successCallback: Callback,
errorCallback: Callback
) {
try {
val content = java.io.File(path).readText()
successCallback.invoke(content)
} catch (e: Exception) {
errorCallback.invoke(e.message)
}
}
// JavaScript
NativeModules.FileModule.readFile(
'/data/test.txt',
(content) => console.log(content),
(error) => console.error(error)
);All lessons in this course
- Writing a Legacy Native Module in Kotlin
- Writing a Legacy Native Module in Swift
- Turbo Native Modules with JSI
- Async Callbacks, Promises, and Events from Native