From 14ec6f011e2afd32489345a6efec02623d9a31fd Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Mon, 15 Feb 2016 13:33:28 -0800 Subject: [PATCH] Use promises in 'NetInfo' Reviewed By: svcscm Differential Revision: D2938010 fb-gh-sync-id: 4a24ce680b37e49759f3325987b4b440eb033b94 shipit-source-id: 4a24ce680b37e49759f3325987b4b440eb033b94 --- Examples/UIExplorer/NetInfoExample.js | 4 +-- Libraries/Network/NetInfo.js | 34 ++++++++----------- Libraries/Network/RCTNetInfo.m | 6 ++-- Libraries/Utilities/deprecatedCallback.js | 14 +++++--- .../react/modules/netinfo/NetInfoModule.java | 22 +++++------- 5 files changed, 39 insertions(+), 41 deletions(-) diff --git a/Examples/UIExplorer/NetInfoExample.js b/Examples/UIExplorer/NetInfoExample.js index a79ed67e2..97af9e1e0 100644 --- a/Examples/UIExplorer/NetInfoExample.js +++ b/Examples/UIExplorer/NetInfoExample.js @@ -134,8 +134,8 @@ const IsConnectionExpensive = React.createClass({ }; }, _checkIfExpensive() { - NetInfo.isConnectionExpensive( - (isConnectionExpensive) => { this.setState({isConnectionExpensive}); } + NetInfo.isConnectionExpensive().then( + isConnectionExpensive => { this.setState({isConnectionExpensive}); } ); }, render() { diff --git a/Libraries/Network/NetInfo.js b/Libraries/Network/NetInfo.js index 474ffd8f5..5399be025 100644 --- a/Libraries/Network/NetInfo.js +++ b/Libraries/Network/NetInfo.js @@ -16,6 +16,7 @@ const NativeModules = require('NativeModules'); const Platform = require('Platform'); const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); const RCTNetInfo = NativeModules.NetInfo; +const deprecatedCallback = require('deprecatedCallback'); const DEVICE_CONNECTIVITY_EVENT = 'networkStatusDidChange'; @@ -135,8 +136,12 @@ const _isConnectedSubscriptions = new Map(); * monetary costs, data limitations or battery/performance issues. * * ``` - * NetInfo.isConnectionExpensive((isConnectionExpensive) => { + * NetInfo.isConnectionExpensive() + * .then(isConnectionExpensive => { * console.log('Connection is ' + (isConnectionExpensive ? 'Expensive' : 'Not Expensive')); + * }) + * .catch(error => { + * console.error(error); * }); * ``` * @@ -146,7 +151,7 @@ const _isConnectedSubscriptions = new Map(); * internet connectivity. * * ``` - * NetInfo.isConnected.fetch().done((isConnected) => { + * NetInfo.isConnected.fetch().then(isConnected => { * console.log('First, is ' + (isConnected ? 'online' : 'offline')); * }); * function handleFirstConnectivityChange(isConnected) { @@ -192,14 +197,7 @@ const NetInfo = { }, fetch(): Promise { - return new Promise((resolve, reject) => { - RCTNetInfo.getCurrentConnectivity( - function(resp) { - resolve(resp.network_info); - }, - reject - ); - }); + return RCTNetInfo.getCurrentConnectivity().then(resp => resp.network_info); }, isConnected: { @@ -239,15 +237,13 @@ const NetInfo = { }, }, - isConnectionExpensive(callback: (metered: ?boolean, error?: string) => void): void { - if (Platform.OS === 'android') { - RCTNetInfo.isConnectionMetered((_isMetered) => { - callback(_isMetered); - }); - } else { - // TODO t9296080 consider polyfill and more features later on - callback(null, "Unsupported"); - } + isConnectionExpensive(): Promise { + return deprecatedCallback( + Platform.OS === 'android' ? RCTNetInfo.isConnectionMetered() : Promise.reject(new Error('Currently not supported on iOS')), + Array.prototype.slice.call(arguments), + 'single-callback-value-first', + 'NetInfo.isConnectionMetered(callback) is deprecated. Use the returned Promise instead.' + ); }, }; diff --git a/Libraries/Network/RCTNetInfo.m b/Libraries/Network/RCTNetInfo.m index 78e1c3ab7..067996b6c 100644 --- a/Libraries/Network/RCTNetInfo.m +++ b/Libraries/Network/RCTNetInfo.m @@ -87,10 +87,10 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC #pragma mark - Public API // TODO: remove error callback - not needed except by Subscribable interface -RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTResponseSenderBlock)getSuccess - withErrorCallback:(__unused RCTResponseSenderBlock)getError) +RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTPromiseResolveBlock)resolve + reject:(__unused RCTPromiseRejectBlock)reject) { - getSuccess(@[@{@"network_info": _status}]); + resolve(@[@{@"network_info": _status}]); } @end diff --git a/Libraries/Utilities/deprecatedCallback.js b/Libraries/Utilities/deprecatedCallback.js index 8ed31254b..3beefdc48 100644 --- a/Libraries/Utilities/deprecatedCallback.js +++ b/Libraries/Utilities/deprecatedCallback.js @@ -19,7 +19,7 @@ module.exports = function(promise: Promise, callbacks: Array, type: st return promise; } - let success, error; + let success, error, callback; console.warn(warning); @@ -36,13 +36,19 @@ module.exports = function(promise: Promise, callbacks: Array, type: st res => success(res), err => error(err) ); - case 'node': // handles func(callback) - const [ callback ] = callbacks; + case 'single-callback-value-first': // handles func(callback(value, err)) + [ callback ] = callbacks; + return promise.then( + res => callback(res), + err => callback(null, err) + ); + case 'node': // handles func(callback(err, value)) + [ callback ] = callbacks; return promise.then( res => callback(null, res), err => callback(err) ); default: - throw new Error(`Type of callbacks not specified. Must be one of 'success-first', 'error-first', or 'node'`); + throw new Error(`Type of callbacks not specified. Must be one of 'success-first', 'error-first', 'single-callback-value-first', or 'node'`); } }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java index 463ad17c4..19b571592 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java @@ -17,15 +17,13 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.support.v4.net.ConnectivityManagerCompat; -import com.facebook.common.logging.FLog; -import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.common.ReactConstants; import static com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; @@ -41,6 +39,8 @@ public class NetInfoModule extends ReactContextBaseJavaModule "To use NetInfo on Android, add the following to your AndroidManifest.xml:\n" + ""; + private static final String ERROR_MISSING_PERMISSION = "E_MISSING_PERMISSION"; + private final ConnectivityManager mConnectivityManager; private final ConnectivityManagerCompat mConnectivityManagerCompat; private final ConnectivityBroadcastReceiver mConnectivityBroadcastReceiver; @@ -81,25 +81,21 @@ public class NetInfoModule extends ReactContextBaseJavaModule } @ReactMethod - public void getCurrentConnectivity(Callback successCallback, Callback errorCallback) { + public void getCurrentConnectivity(Promise promise) { if (mNoNetworkPermission) { - if (errorCallback == null) { - FLog.e(ReactConstants.TAG, MISSING_PERMISSION_MESSAGE); - return; - } - errorCallback.invoke(MISSING_PERMISSION_MESSAGE); + promise.reject(ERROR_MISSING_PERMISSION, MISSING_PERMISSION_MESSAGE, null); return; } - successCallback.invoke(createConnectivityEventMap()); + promise.resolve(createConnectivityEventMap()); } @ReactMethod - public void isConnectionMetered(Callback successCallback) { + public void isConnectionMetered(Promise promise) { if (mNoNetworkPermission) { - FLog.e(ReactConstants.TAG, MISSING_PERMISSION_MESSAGE); + promise.reject(ERROR_MISSING_PERMISSION, MISSING_PERMISSION_MESSAGE, null); return; } - successCallback.invoke(mConnectivityManagerCompat.isActiveNetworkMetered(mConnectivityManager)); + promise.resolve(ConnectivityManagerCompat.isActiveNetworkMetered(mConnectivityManager)); } private void registerReceiver() {