Update hooks api to support promise api

This commit is contained in:
Nick O'Leary 2021-04-15 15:11:27 +01:00
parent ed351eee54
commit 22df59e229
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
2 changed files with 82 additions and 9 deletions

View File

@ -8,7 +8,12 @@ const VALID_HOOKS = [
"postDeliver", "postDeliver",
"onReceive", "onReceive",
"postReceive", "postReceive",
"onComplete" "onComplete",
// Module install hooks
"preInstall",
"postInstall",
"preUninstall",
"postUninstall"
] ]
@ -35,12 +40,12 @@ let labelledHooks = { }
* - `postReceive` - passed a `ReceiveEvent` when the message has been given to the node's `input` handler(s) * - `postReceive` - passed a `ReceiveEvent` when the message has been given to the node's `input` handler(s)
* - `onComplete` - passed a `CompleteEvent` when the node has completed with a message or logged an error * - `onComplete` - passed a `CompleteEvent` when the node has completed with a message or logged an error
* *
* @mixin @node-red/runtime_hooks * @mixin @node-red/util_hooks
*/ */
/** /**
* Register a handler to a named hook * Register a handler to a named hook
* @memberof @node-red/runtime_hooks * @memberof @node-red/util_hooks
* @param {String} hookId - the name of the hook to attach to * @param {String} hookId - the name of the hook to attach to
* @param {Function} callback - the callback function for the hook * @param {Function} callback - the callback function for the hook
*/ */
@ -68,7 +73,7 @@ function add(hookId, callback) {
/** /**
* Remove a handled from a named hook * Remove a handled from a named hook
* @memberof @node-red/runtime_hooks * @memberof @node-red/util_hooks
* @param {String} hookId - the name of the hook event to remove - must be `name.label` * @param {String} hookId - the name of the hook event to remove - must be `name.label`
*/ */
function remove(hookId) { function remove(hookId) {
@ -110,11 +115,33 @@ function removeHook(id,callback) {
function trigger(hookId, payload, done) { function trigger(hookId, payload, done) {
const hookStack = hooks[hookId]; const hookStack = hooks[hookId];
if (!hookStack || hookStack.length === 0) { if (!hookStack || hookStack.length === 0) {
done(); if (done) {
return; done();
return;
} else {
return Promise.resolve();
}
} }
if (!done) {
return new Promise((resolve,reject) => {
invokeStack(hookStack,payload,function(err) {
if (err !== undefined && err !== false) {
if (!(err instanceof Error)) {
err = new Error(err);
}
err.hook = hookId
reject(err);
} else {
resolve(err);
}
})
});
} else {
invokeStack(hookStack,payload,done)
}
}
function invokeStack(hookStack,payload,done) {
let i = 0; let i = 0;
function callNextHook(err) { function callNextHook(err) {
if (i === hookStack.length || err) { if (i === hookStack.length || err) {
done(err); done(err);
@ -148,8 +175,6 @@ function trigger(hookId, payload, done) {
} }
} }
} }
callNextHook();
function handleResolve(result) { function handleResolve(result) {
if (result === undefined) { if (result === undefined) {
callNextHook(); callNextHook();
@ -157,6 +182,7 @@ function trigger(hookId, payload, done) {
done(result); done(result);
} }
} }
callNextHook();
} }
function clear() { function clear() {

View File

@ -249,4 +249,51 @@ describe("util/hooks", function() {
done(); done();
}) })
}) })
it("handler can use callback function - promise API", function(done) {
hooks.add("onSend.A", function(payload, done) {
setTimeout(function() {
payload.order.push("A")
done()
},30)
})
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
let data = { order:[] };
hooks.trigger("onSend",data).then(() => {
data.order.should.eql(["A","B"])
done()
}).catch(done)
})
it("handler can halt execution - promise API", function(done) {
hooks.add("onSend.A", function(payload, done) {
setTimeout(function() {
payload.order.push("A")
done(false)
},30)
})
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
let data = { order:[] };
hooks.trigger("onSend",data).then(() => {
data.order.should.eql(["A"])
done()
}).catch(done)
})
it("handler can halt execution on error - promise API", function(done) {
hooks.add("onSend.A", function(payload, done) {
throw new Error("error");
})
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
let data = { order:[] };
hooks.trigger("onSend",data).then(() => {
done("hooks.trigger resolved unexpectedly")
}).catch(err => {
done();
})
})
}); });