-
Notifications
You must be signed in to change notification settings - Fork 35
/
native-bridge.es
85 lines (76 loc) · 2.41 KB
/
native-bridge.es
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*!
* Copyright (c) 2014-present Cliqz GmbH. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { NativeModules, NativeEventEmitter } from 'react-native';
import events from '../core/events';
import console from './console';
const nativeBridge = NativeModules.JSBridge;
/**
* Makes a synchronous function behave like a promise
* @param {Function} fn synchronous function to wrap
* @return {Function} Function which wraps a call to this function in a Promise
*/
function makePromise(fn) {
return (...args) => {
try {
const ret = fn(...args);
return Promise.resolve(ret);
} catch (e) {
return Promise.reject(e);
}
};
}
export default class Bridge {
constructor() {
(nativeBridge.events || []).forEach((event) => {
events.subscribe(event, (...args) => {
nativeBridge.pushEvent(event, args);
});
});
this.isActive = false;
this.eventQueue = [];
this.registeredActions = {};
this.eventEmitter = new NativeEventEmitter(nativeBridge);
this.eventEmitter.addListener('callAction', this.onAction.bind(this));
this.eventEmitter.addListener('publishEvent', this.onEvent.bind(this));
}
onAction({ id, action, args }) {
const fn = this.registeredActions[action];
if (!fn) {
nativeBridge.replyToAction(id, { error: 'invalid action' });
return;
}
const call = fn(...(args || []));
call.then((ret) => {
nativeBridge.replyToAction(id, { result: ret });
}, (e) => {
console.log('onAction err', e);
nativeBridge.replyToAction(id, { error: 'exception when running action' });
});
}
onEvent(argument) {
if (!this.isActive) {
this.eventQueue.push([argument]);
} else {
const { event, args } = argument;
console.log('broadcast native event', event, args);
events.pub(event, ...(args || []));
}
}
activate() {
this.isActive = true;
this.eventQueue.forEach(eventArgs => this.onEvent(...eventArgs));
this.eventQueue = [];
}
registerAction(name, fn, isPromise) {
if (this.registeredActions[name] !== undefined) {
throw new Error('action already exists');
}
this.registeredActions[name] = isPromise ? fn : makePromise(fn);
nativeBridge.registerAction(name);
}
}