[Bridge] Add support for JS async functions to RCT_EXPORT_METHOD

Summary:
Adds support for JS async methods and helps guide people writing native modules w.r.t. the callbacks. With this diff, on the native side you write:

```objc
RCT_EXPORT_METHOD(getValueAsync:(NSString *)key
                       resolver:(RCTPromiseResolver)resolve
                       rejecter:(RCTPromiseRejecter)reject)
{
  NSError *error = nil;
  id value = [_nativeDataStore valueForKey:key error:&error];

  // "resolve" and "reject" are automatically defined blocks that take
  // any object (nil is OK) and an NSError, respectively
  if (!error) {
    resolve(value);
  } else {
    reject(error);
  }
}
```

On the JS side, you can write:

```js
var {DemoDataStore} = require('react-native').NativeModules;
DemoDataStore.getValueAsync('sample-key').then((value) => {
  console.log('Got:', value);
}, (error) => {
  console.error(error);
  // "error" is an Error object whose message is the NSError's description.
  // The NSError's code and domain are also set, and the native trace i
Closes https://github.com/facebook/react-native/pull/1232
Github Author: James Ide <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
This commit is contained in:
James Ide
2015-06-01 09:47:41 -07:00
parent 2b4daf228d
commit d548c85da6
4 changed files with 181 additions and 30 deletions

View File

@@ -431,14 +431,14 @@ var MessageQueueMixin = {
},
/**
* @param {Function} onFail Function to store in current thread for later
* lookup, when request fails.
* @param {Function} onSucc Function to store in current thread for later
* lookup, when request succeeds.
* @param {Function} onFail Function to store in current thread for later
* lookup, when request fails.
* @param {Object?=} scope Scope to invoke `cb` with.
* @param {Object?=} res Resulting callback ids. Use `this._POOLED_CBIDS`.
*/
_storeCallbacksInCurrentThread: function(onFail, onSucc, scope) {
_storeCallbacksInCurrentThread: function(onSucc, onFail, scope) {
invariant(onFail || onSucc, INTERNAL_ERROR);
this._bookkeeping.allocateCallbackIDs(this._POOLED_CBIDS);
var succCBID = this._POOLED_CBIDS.successCallbackID;
@@ -494,7 +494,7 @@ var MessageQueueMixin = {
return ret;
},
call: function(moduleName, methodName, params, onFail, onSucc, scope) {
call: function(moduleName, methodName, params, onSucc, onFail, scope) {
invariant(
(!onFail || typeof onFail === 'function') &&
(!onSucc || typeof onSucc === 'function'),
@@ -502,10 +502,10 @@ var MessageQueueMixin = {
);
// Store callback _before_ sending the request, just in case the MailBox
// returns the response in a blocking manner.
if (onSucc) {
this._storeCallbacksInCurrentThread(onFail, onSucc, scope, this._POOLED_CBIDS);
if (onSucc || onFail) {
this._storeCallbacksInCurrentThread(onSucc, onFail, scope, this._POOLED_CBIDS);
onSucc && params.push(this._POOLED_CBIDS.successCallbackID);
onFail && params.push(this._POOLED_CBIDS.errorCallbackID);
params.push(this._POOLED_CBIDS.successCallbackID);
}
var moduleID = this._remoteModuleNameToModuleID[moduleName];
if (moduleID === undefined || moduleID === null) {