mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-11 17:21:11 +08:00
[ReactNative] Allow bridge modules to run on the JavaScript thread
This commit is contained in:
@@ -31,6 +31,8 @@
|
||||
NSString *const RCTReloadNotification = @"RCTReloadNotification";
|
||||
NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification";
|
||||
|
||||
dispatch_queue_t const RCTJSThread = nil;
|
||||
|
||||
/**
|
||||
* Must be kept in sync with `MessageQueue.js`.
|
||||
*/
|
||||
@@ -795,6 +797,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
_bundleURL = bundleURL;
|
||||
_moduleProvider = block;
|
||||
_launchOptions = [launchOptions copy];
|
||||
|
||||
[self setUp];
|
||||
[self bindKeys];
|
||||
}
|
||||
@@ -872,6 +875,8 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
dispatch_queue_t queue = [module methodQueue];
|
||||
if (queue) {
|
||||
_queuesByID[moduleID] = queue;
|
||||
} else {
|
||||
_queuesByID[moduleID] = [NSNull null];
|
||||
}
|
||||
}
|
||||
}];
|
||||
@@ -1128,6 +1133,16 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
|
||||
#pragma mark - Payload Generation
|
||||
|
||||
- (void)dispatchBlock:(dispatch_block_t)block forModule:(NSNumber *)moduleID
|
||||
{
|
||||
id queue = _queuesByID[moduleID];
|
||||
if (queue == [NSNull null]) {
|
||||
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
|
||||
} else {
|
||||
dispatch_async(queue ?: _methodQueue, block);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args context:(NSNumber *)context
|
||||
{
|
||||
#if BATCHED_BRIDGE
|
||||
@@ -1235,10 +1250,9 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
// TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case?
|
||||
[_modulesByID enumerateObjectsUsingBlock:^(id<RCTBridgeModule> module, NSNumber *moduleID, BOOL *stop) {
|
||||
if ([module respondsToSelector:@selector(batchDidComplete)]) {
|
||||
dispatch_queue_t queue = _queuesByID[moduleID];
|
||||
dispatch_async(queue ?: _methodQueue, ^{
|
||||
[self dispatchBlock:^{
|
||||
[module batchDidComplete];
|
||||
});
|
||||
} forModule:moduleID];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -1273,8 +1287,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
}
|
||||
|
||||
__weak RCTBridge *weakSelf = self;
|
||||
dispatch_queue_t queue = _queuesByID[moduleID];
|
||||
dispatch_async(queue ?: _methodQueue, ^{
|
||||
[self dispatchBlock:^{
|
||||
RCTProfileBeginEvent();
|
||||
__strong RCTBridge *strongSelf = weakSelf;
|
||||
|
||||
@@ -1303,7 +1316,7 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
@"method": method.JSMethodName,
|
||||
@"selector": NSStringFromSelector(method.selector),
|
||||
});
|
||||
});
|
||||
} forModule:@(moduleID)];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
*/
|
||||
typedef void (^RCTResponseSenderBlock)(NSArray *response);
|
||||
|
||||
/**
|
||||
* This constant can be returned from +methodQueue to force module
|
||||
* methods to be called on the JavaScript thread. This can have serious
|
||||
* implications for performance, so only use this if you're sure it's what
|
||||
* you need.
|
||||
*
|
||||
* NOTE: RCTJSThread is not a real libdispatch queue
|
||||
*/
|
||||
extern const dispatch_queue_t RCTJSThread;
|
||||
|
||||
/**
|
||||
* Provides the interface needed to register a bridge module.
|
||||
*/
|
||||
|
||||
@@ -307,12 +307,17 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError)
|
||||
|
||||
- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
{
|
||||
if ([NSThread currentThread] != _javaScriptThread) {
|
||||
[self performSelector:@selector(executeBlockOnJavaScriptQueue:)
|
||||
onThread:_javaScriptThread withObject:block waitUntilDone:NO];
|
||||
} else {
|
||||
block();
|
||||
}
|
||||
/**
|
||||
* Always dispatch async, ensure there are no sync calls on the JS thread
|
||||
* otherwise timers can cause a deadlock
|
||||
*/
|
||||
[self performSelector:@selector(_runBlock:)
|
||||
onThread:_javaScriptThread withObject:block waitUntilDone:NO];
|
||||
}
|
||||
|
||||
- (void)_runBlock:(dispatch_block_t)block
|
||||
{
|
||||
block();
|
||||
}
|
||||
|
||||
- (void)injectJSONText:(NSString *)script
|
||||
|
||||
@@ -110,7 +110,7 @@ RCT_IMPORT_METHOD(RCTJSTimers, callTimers)
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
return RCTJSThread;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
@@ -131,8 +131,6 @@ RCT_IMPORT_METHOD(RCTJSTimers, callTimers)
|
||||
|
||||
- (void)startTimers
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
if (![self isValid] || _timers.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user