Skip to content

Commit

Permalink
refactor(hooks): better error handling
Browse files Browse the repository at this point in the history
Hook listeners can both throw and reject, and it will be handled appropriately (e.g. filters won't fail)
  • Loading branch information
julianlam committed Jan 27, 2021
1 parent 8ff07bc commit e7bd038
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions public/src/modules/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,30 @@ define('hooks', [], () => {
loaded: {},
};

Hooks.register = (hookName, listener) => {
Hooks.register = (hookName, method) => {
Hooks.loaded[hookName] = Hooks.loaded[hookName] || new Set();
Hooks.loaded[hookName].add(listener);
Hooks.loaded[hookName].add(method);
};
Hooks.on = Hooks.register;

Hooks.hasListeners = hookName => Hooks.loaded[hookName] && Hooks.loaded[hookName].length > 0;

const _onHookError = (e, listener, data) => {
console.warn(`[hooks] Exception encountered in ${listener.name ? listener.name : 'anonymous function'}, stack trace follows.`);
console.error(e);
return Promise.resolve(data);
};

const _fireFilterHook = (hookName, data) => {
const listeners = Array.from(Hooks.loaded[hookName]);
return listeners.reduce((promise, listener) => promise.then(data => listener(data)), Promise.resolve(data));
return listeners.reduce((promise, listener) => promise.then((data) => {
try {
const result = listener(data);
return utils.isPromise(result) ? result.then(data => Promise.resolve(data)).catch(e => _onHookError(e, listener, data)) : result;
} catch (e) {
return _onHookError(e, listener, data);
}
}), Promise.resolve(data));
};

const _fireActionHook = (hookName, data) => {
Expand All @@ -27,7 +40,13 @@ define('hooks', [], () => {

const _fireStaticHook = (hookName, data) => {
const listeners = Array.from(Hooks.loaded[hookName]);
return Promise.allSettled(listeners.map(listener => listener(data))).then(() => Promise.resolve(data));
return Promise.allSettled(listeners.map((listener) => {
try {
return listener(data);
} catch (e) {
return _onHookError(e, listener);
}
})).then(() => Promise.resolve(data));
};

Hooks.fire = (hookName, data) => {
Expand Down

0 comments on commit e7bd038

Please sign in to comment.