2020-04-03 11:50:54 +00:00
|
|
|
const getObserversByPriority = ( observers, eventType ) => {
|
|
|
|
return observers[ eventType ]
|
|
|
|
? Array.from( observers[ eventType ].values() ).sort( ( a, b ) => {
|
|
|
|
return b.priority - a.priority;
|
|
|
|
} )
|
|
|
|
: [];
|
|
|
|
};
|
|
|
|
|
2020-03-20 16:46:24 +00:00
|
|
|
/**
|
|
|
|
* Emits events on registered observers for the provided type and passes along
|
|
|
|
* the provided data.
|
|
|
|
*
|
|
|
|
* This event emitter will silently catch promise errors, but doesn't care
|
|
|
|
* otherwise if any errors are caused by observers. So events that do care
|
|
|
|
* should use `emitEventWithAbort` instead.
|
|
|
|
*
|
|
|
|
* @param {Object} observers The registered observers to omit to.
|
|
|
|
* @param {string} eventType The event type being emitted.
|
|
|
|
* @param {*} data Data passed along to the observer when it is
|
|
|
|
* invoked.
|
|
|
|
*
|
|
|
|
* @return {Promise} A promise that resolves to true after all observers have
|
|
|
|
* executed.
|
|
|
|
*/
|
|
|
|
export const emitEvent = async ( observers, eventType, data ) => {
|
2020-04-03 11:50:54 +00:00
|
|
|
const observersByType = getObserversByPriority( observers, eventType );
|
2020-04-02 09:27:54 +00:00
|
|
|
for ( const observer of observersByType ) {
|
2020-03-20 16:46:24 +00:00
|
|
|
try {
|
2020-04-03 11:50:54 +00:00
|
|
|
await Promise.resolve( observer.callback( data ) );
|
2020-03-20 16:46:24 +00:00
|
|
|
} catch ( e ) {
|
|
|
|
// we don't care about errors blocking execution, but will
|
|
|
|
// console.error for troubleshooting.
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.error( e );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emits events on registered observers for the provided type and passes along
|
|
|
|
* the provided data. This event emitter will abort and return any value from
|
|
|
|
* observers that do not return true.
|
|
|
|
*
|
|
|
|
* @param {Object} observers The registered observers to omit to.
|
|
|
|
* @param {string} eventType The event type being emitted.
|
|
|
|
* @param {*} data Data passed along to the observer when it is
|
|
|
|
* invoked.
|
|
|
|
*
|
|
|
|
* @return {Promise} Returns a promise that resolves to either boolean or the
|
|
|
|
* return value of the aborted observer.
|
|
|
|
*/
|
|
|
|
export const emitEventWithAbort = async ( observers, eventType, data ) => {
|
2020-04-03 11:50:54 +00:00
|
|
|
const observersByType = getObserversByPriority( observers, eventType );
|
2020-04-02 09:27:54 +00:00
|
|
|
for ( const observer of observersByType ) {
|
2020-03-20 16:46:24 +00:00
|
|
|
try {
|
2020-04-03 11:50:54 +00:00
|
|
|
const response = await Promise.resolve( observer.callback( data ) );
|
2020-03-20 16:46:24 +00:00
|
|
|
if ( response !== true ) {
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
} catch ( e ) {
|
|
|
|
// we don't handle thrown errors but just console.log for
|
|
|
|
// troubleshooting
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.error( e );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|