I have this test before hook:
module.exports = function (options = {}) { // eslint-disable-line no-unused-vars
const hookTest = function() {
return function(hook) {
return hook.app.service('myservice').find({
query: {
name: hook.data.name
}
})
.then(result => {
if (result.data.length === 1){
return Promise.resolve(hook);//Works fine
} else {
throw 'PCU'; //throw an error. Record must exist
}
})
.catch(error => {
throw new errors.BadRequest(error, { datos: hook.data });
//UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): BadRequest: PCU
});
};
};
};
Cancel hook chain without UnhandledPromiseRejectionWarning
UnhandledPromiseRejectionWarning
Module versions (especially the part that's not working):
feathers-cli version 2.2.1
NodeJS version:
v6.9.2
Don't know if this helps but if you'd like to stop the hook chain without raising an error you can simply set the result like this: hook.result = xxx. However if you'd like to raise an error simply throw a Feathers error directly in your then statement:
if (xxx) {
throw new errors.BadRequest('PCU')
}
Seems to be expected behaviour since you raise an error in your catch that is not catched at a higher level.
You could set hook.cancelled = true and then wrap everything that should into a iff hook checking iff(hook => !hook.cancelled, otherHooks)
@claustres @daffl Thank you. I'll try later.
According to https://docs.feathersjs.com/api/hooks.html#hook-functions, a hook can thow an error or rejects with an error. Should the documentation be changed?
@claustres Setting context.result prevents the DB call. It does not prevent the remaining before & after hooks from running (https://github.com/feathersjs/feathers-hooks-common/issues/236).
@claustres If "raise an error simply throw a Feathers error directly in your then statement", I get UnhandledPromiseRejectionWarning too
@daffl hook.cancelled = true and iff(hook => !hook.cancelled, otherHooks) works, but the operation is done in the database.
Would I need to mix both options? (setting context.result AND iff(hook => !hook.cancelled, otherHooks))
The problem is that in your catch you throw again and this error will not get catched by anyone if you don't have a higher catch block in your app, so the UnhandledPromiseRejectionWarning will eventually popup. For me the 2 throws are redondent. As far as I understand hooks can throw errors but you have to catch them at higher level if you don't want to have the UnhandledPromiseRejectionWarning.
What I can tell is that in my case I use a before hook to check for permissions. When the check fails on a create for instance I throw an error and set the result to null. Don't know which of both things does the job (or if it is actually a mix) but the object is not created in DB neither other hooks are ran.
@claustres Thank you. Next week I will do several tests and I will share the result
I have generated a new app using feathers-cli with 1 service and 1 hook. Code is here: https://github.com/kfern/feathers-issues/tree/feathers-issues-635
In generated hook source comments "Hooks can either return nothing or a promise" and return a promise. Generated hook test only check if the hook returns a Promise.
@daffl Can a hook only return a promise?
Yes a hook can return a promise only, this is the main behaviour for async hooks https://docs.feathersjs.com/api/hooks.html#asynchronous-hooks, if you don't have such async operations you can return nothing at all. In both cases what you do usually is simply to alter the hook object (typically hook.dataor hook.params).
A hook can return either a value (the new hook object) or a promise because promises consider values as resolved promises.
So return {} and return Promise.resolve({}) are eqivalent.
Closing since I think all questions should be answered. To skip a hook setting hook.cancelled and checking for iff(hook => !hook.cancelled, otherHooks), to skip the database call hook.result can be set in a before hook.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.
Most helpful comment
Closing since I think all questions should be answered. To skip a hook setting
hook.cancelledand checking foriff(hook => !hook.cancelled, otherHooks), to skip the database callhook.resultcan be set in abeforehook.