This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
7.2 KiB
218 lines
7.2 KiB
/** |
|
* Copyright (c) 2015-present, Facebook, Inc. |
|
* |
|
* This source code is licensed under the MIT license found in the |
|
* LICENSE file in the root directory of this source tree. |
|
* |
|
* @providesModule EventEmitter |
|
* @noflow |
|
* @typecheck |
|
*/ |
|
'use strict'; |
|
|
|
const EmitterSubscription = require('EmitterSubscription'); |
|
const EventSubscriptionVendor = require('EventSubscriptionVendor'); |
|
|
|
const emptyFunction = require('fbjs/lib/emptyFunction'); |
|
const invariant = require('fbjs/lib/invariant'); |
|
|
|
/** |
|
* @class EventEmitter |
|
* @description |
|
* An EventEmitter is responsible for managing a set of listeners and publishing |
|
* events to them when it is told that such events happened. In addition to the |
|
* data for the given event it also sends a event control object which allows |
|
* the listeners/handlers to prevent the default behavior of the given event. |
|
* |
|
* The emitter is designed to be generic enough to support all the different |
|
* contexts in which one might want to emit events. It is a simple multicast |
|
* mechanism on top of which extra functionality can be composed. For example, a |
|
* more advanced emitter may use an EventHolder and EventFactory. |
|
*/ |
|
class EventEmitter { |
|
|
|
_subscriber: EventSubscriptionVendor; |
|
_currentSubscription: ?EmitterSubscription; |
|
|
|
/** |
|
* @constructor |
|
* |
|
* @param {EventSubscriptionVendor} subscriber - Optional subscriber instance |
|
* to use. If omitted, a new subscriber will be created for the emitter. |
|
*/ |
|
constructor(subscriber: ?EventSubscriptionVendor) { |
|
this._subscriber = subscriber || new EventSubscriptionVendor(); |
|
} |
|
|
|
/** |
|
* Adds a listener to be invoked when events of the specified type are |
|
* emitted. An optional calling context may be provided. The data arguments |
|
* emitted will be passed to the listener function. |
|
* |
|
* TODO: Annotate the listener arg's type. This is tricky because listeners |
|
* can be invoked with varargs. |
|
* |
|
* @param {string} eventType - Name of the event to listen to |
|
* @param {function} listener - Function to invoke when the specified event is |
|
* emitted |
|
* @param {*} context - Optional context object to use when invoking the |
|
* listener |
|
*/ |
|
addListener( |
|
eventType: string, listener: Function, context: ?Object): EmitterSubscription { |
|
|
|
return (this._subscriber.addSubscription( |
|
eventType, |
|
new EmitterSubscription(this, this._subscriber, listener, context) |
|
) : any); |
|
} |
|
|
|
/** |
|
* Similar to addListener, except that the listener is removed after it is |
|
* invoked once. |
|
* |
|
* @param {string} eventType - Name of the event to listen to |
|
* @param {function} listener - Function to invoke only once when the |
|
* specified event is emitted |
|
* @param {*} context - Optional context object to use when invoking the |
|
* listener |
|
*/ |
|
once(eventType: string, listener: Function, context: ?Object): EmitterSubscription { |
|
return this.addListener(eventType, (...args) => { |
|
this.removeCurrentListener(); |
|
listener.apply(context, args); |
|
}); |
|
} |
|
|
|
/** |
|
* Removes all of the registered listeners, including those registered as |
|
* listener maps. |
|
* |
|
* @param {?string} eventType - Optional name of the event whose registered |
|
* listeners to remove |
|
*/ |
|
removeAllListeners(eventType: ?string) { |
|
this._subscriber.removeAllSubscriptions(eventType); |
|
} |
|
|
|
/** |
|
* Provides an API that can be called during an eventing cycle to remove the |
|
* last listener that was invoked. This allows a developer to provide an event |
|
* object that can remove the listener (or listener map) during the |
|
* invocation. |
|
* |
|
* If it is called when not inside of an emitting cycle it will throw. |
|
* |
|
* @throws {Error} When called not during an eventing cycle |
|
* |
|
* @example |
|
* var subscription = emitter.addListenerMap({ |
|
* someEvent: function(data, event) { |
|
* console.log(data); |
|
* emitter.removeCurrentListener(); |
|
* } |
|
* }); |
|
* |
|
* emitter.emit('someEvent', 'abc'); // logs 'abc' |
|
* emitter.emit('someEvent', 'def'); // does not log anything |
|
*/ |
|
removeCurrentListener() { |
|
invariant( |
|
!!this._currentSubscription, |
|
'Not in an emitting cycle; there is no current subscription' |
|
); |
|
this.removeSubscription(this._currentSubscription); |
|
} |
|
|
|
/** |
|
* Removes a specific subscription. Called by the `remove()` method of the |
|
* subscription itself to ensure any necessary cleanup is performed. |
|
*/ |
|
removeSubscription(subscription: EmitterSubscription) { |
|
invariant( |
|
subscription.emitter === this, |
|
'Subscription does not belong to this emitter.' |
|
); |
|
this._subscriber.removeSubscription(subscription); |
|
} |
|
|
|
/** |
|
* Returns an array of listeners that are currently registered for the given |
|
* event. |
|
* |
|
* @param {string} eventType - Name of the event to query |
|
* @returns {array} |
|
*/ |
|
listeners(eventType: string): [EmitterSubscription] { |
|
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any); |
|
return subscriptions |
|
? subscriptions.filter(emptyFunction.thatReturnsTrue).map( |
|
function(subscription) { |
|
return subscription.listener; |
|
}) |
|
: []; |
|
} |
|
|
|
/** |
|
* Emits an event of the given type with the given data. All handlers of that |
|
* particular type will be notified. |
|
* |
|
* @param {string} eventType - Name of the event to emit |
|
* @param {...*} Arbitrary arguments to be passed to each registered listener |
|
* |
|
* @example |
|
* emitter.addListener('someEvent', function(message) { |
|
* console.log(message); |
|
* }); |
|
* |
|
* emitter.emit('someEvent', 'abc'); // logs 'abc' |
|
*/ |
|
emit(eventType: string) { |
|
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any); |
|
if (subscriptions) { |
|
for (let i = 0, l = subscriptions.length; i < l; i++) { |
|
const subscription = subscriptions[i]; |
|
|
|
// The subscription may have been removed during this event loop. |
|
if (subscription) { |
|
this._currentSubscription = subscription; |
|
subscription.listener.apply( |
|
subscription.context, |
|
Array.prototype.slice.call(arguments, 1) |
|
); |
|
} |
|
} |
|
this._currentSubscription = null; |
|
} |
|
} |
|
|
|
/** |
|
* Removes the given listener for event of specific type. |
|
* |
|
* @param {string} eventType - Name of the event to emit |
|
* @param {function} listener - Function to invoke when the specified event is |
|
* emitted |
|
* |
|
* @example |
|
* emitter.removeListener('someEvent', function(message) { |
|
* console.log(message); |
|
* }); // removes the listener if already registered |
|
* |
|
*/ |
|
removeListener(eventType: String, listener) { |
|
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any); |
|
if (subscriptions) { |
|
for (let i = 0, l = subscriptions.length; i < l; i++) { |
|
const subscription = subscriptions[i]; |
|
|
|
// The subscription may have been removed during this event loop. |
|
// its listener matches the listener in method parameters |
|
if (subscription && subscription.listener === listener) { |
|
subscription.remove(); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
module.exports = EventEmitter;
|
|
|