Merge pull request #1984 from OrigenStudio/run-callbacks-await-between-hooks

Await between hooks in runCallbacks
This commit is contained in:
Sacha Greif 2018-05-19 20:48:38 +09:00 committed by GitHub
commit ff7fd0edcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 4 deletions

View file

@ -1,4 +1,5 @@
import { debug } from './debug.js';
import { Utils } from './utils';
/**
* @summary A list of all registered callback hooks
@ -67,15 +68,15 @@ export const runCallbacks = function () {
const item = arguments[1];
// successive arguments are passed to each iteration
const args = Array.prototype.slice.call(arguments).slice(2);
// flag used to detect the callback that initiated the async context
let asyncContext = false;
const callbacks = Array.isArray(hook) ? hook : Callbacks[hook];
if (typeof callbacks !== "undefined" && !!callbacks.length) { // if the hook exists, and contains callbacks to run
return callbacks.reduce(function (accumulator, callback) {
const runCallback = (accumulator, callback) => {
debug(`\x1b[32m>> Running callback [${callback.name}] on hook [${hook}]\x1b[0m`);
const newArguments = [accumulator].concat(args);
try {
@ -89,7 +90,7 @@ export const runCallbacks = function () {
if (typeof result === 'undefined') {
// if result of current iteration is undefined, don't pass it on
// debug(`// Warning: Sync callback [${callback.name}] in hook [${hook}] didn't return a result!`)
return accumulator
return accumulator;
} else {
return result;
}
@ -105,6 +106,30 @@ export const runCallbacks = function () {
// pass the unchanged accumulator to the next iteration of the loop
return accumulator;
}
};
return callbacks.reduce(function (accumulator, callback, index) {
if (Utils.isPromise(accumulator)) {
if (!asyncContext) {
debug(`\x1b[32m>> Started async context in hook [${hook}] by [${callbacks[index-1].name}]\x1b[0m`);
asyncContext = true;
}
return new Promise((resolve, reject) => {
accumulator
.then(result => {
try {
// run this callback once we have the previous value
resolve(runCallback(result, callback));
} catch (error) {
// error will be thrown only for breaking errors, so throw it up in the promise chain
reject(error);
}
})
.catch(reject);
});
} else {
return runCallback(accumulator, callback);
}
}, item);
} else { // else, just return the item unchanged

View file

@ -13,6 +13,7 @@ import { Routes } from './routes.js';
import { getCollection } from './collections.js';
import set from 'lodash/set';
import get from 'lodash/get';
import isFunction from 'lodash/isFunction';
registerSetting('debug', false, 'Enable debug mode (more verbose logging)');
@ -491,3 +492,5 @@ String.prototype.replaceAll = function(search, replacement) {
var target = this;
return target.replace(new RegExp(search, 'g'), replacement);
};
Utils.isPromise = value => isFunction(get(value, 'then'));