-
Notifications
You must be signed in to change notification settings - Fork 0
EventEmitter.emitParallel
Executes all listeners for specified event in asynchronous parallel when possible. See remarks for explanation of asynchronous parallel execution.
emitter.emitParallel(event, args...);
emitter.emit(event, args...);emit
| Argument | Type | Required | Description |
|---|---|---|---|
| event | string | ✓ | The name of the event. |
| args | any | Arguments given to each listener. |
A promise to a Map (from hash-me library) with keys the listener functions and the values the return value of the corresponding listener function. If a listener function returns a promise, the value in the map is the value to which promise has been resolved.
If any listener or the library itself throws an exception (including unintentional one) the return value is rejected promise with the exception for the reason.
If any listener returns a rejected promise, the promise returned is also rejected with the same reason.
The method returns reject promise with reason ReferenceError if current graph is not dependency graph, e.g. it has cycles. To distinguish between ReferenceError thrown by bug and intentionally, intentional ReferenceError will have code equal to CIRCULAR_REFERENCE string.
The function does not throws an exception, instead it returns rejected promise.
In case of returning rejected promise, it may only some of the listeners be called. Which listeners were called and which were not is implementation dependent. The order of execution the same as returned value by getGroupedListenerList method. If a listener at group n throws an exception or return rejected promise, a listener from group n+1 and following will not be called. However which of the listeners from group n will be called is unknown and untraceable. This means that another asynchronous operation may fail and its promise is rejected, but that would not be seen, because another asynchronous operation failed earlier. But some asynchronous operations that have been already started may succeed, even though as general event had failed.
The basic idea for creating this library is to allow asynchronous operations in listener functions. This is done by returning a promise from the listener. The emit will return promise that will resolve after all such promises are resolved.
Internally javascript can execute at only one place at a time. This means the listener functions are not called really in parallel but in some order. However they could just return a promise which value is resolving for example as requesting the database, external HTTP server and so on. Asynchronous parallelism is what we call when execute next function without waiting the returned promise to be resolved. In that case the emit can wait for more than one operation to complete and more than one promise to be resolved. Waiting for more than one operation to complete is what we call asynchronous parallelism. This is different than real parallelism where more than one operation could run at the same time. Asynchronous only reduce the wait-time, not the run-time. It allows single-threaded application to follow the principle "If I have to wait for something, I can do other things in the meantime".
The base principle behind dependency graph is topological sorting. If a software library depends on some libraries, those libraries should be loaded before the specified library. This forms a dependency graph which is acyclic directed graph. All nodes in that graph can be linearly ordered in array that defines the order of loading and fulfill the above requirement.
In case of parallelism the above mentioned topological sorting does not provide enough information. It doesn't tell which of the libraries can be loaded in parallel.
In the case of listeners generally all listeners without dependencies can be executed in parallel. All that listeners are collected in a group. Then the emitter can execute all listeners that depends only on listeners from the first group. They are collected in the second group. Then a third group follows with dependencies only from the first two groups and so on. All listeners within from nth group can be called in parallel, but listeners from n+1th group should wait all listeners from n group to complete and have their promises resolved.
Dependencies are purely optional feature of that library. If a listener function has dependencies, that listener does not receive any information from them through this library. It is up to listener implementer to define how the listener use the information from their dependencies. For example implemented can store something on a closure or inside the emitter object (which can be indirect instance of EventEmitter through inheritance). This library provides neither limitation, nor requirements of how this is done. It only guarantees the order of which listener functions are called.