Merge pull request #1694 from spurreiter/operation-hook-error
feat: call after operation hook in case of errors
This commit is contained in:
commit
acb667b73d
|
@ -7,6 +7,7 @@
|
|||
|
||||
const async = require('async');
|
||||
const utils = require('./utils');
|
||||
const debug = require('debug')('loopback:observer');
|
||||
|
||||
module.exports = ObserverMixin;
|
||||
|
||||
|
@ -232,7 +233,24 @@ ObserverMixin.notifyObserversAround = function(operation, context, fn, callback)
|
|||
|
||||
function cbForWork(err) {
|
||||
const args = [].slice.call(arguments, 0);
|
||||
if (err) return callback.apply(null, args);
|
||||
if (err) {
|
||||
// call observer in case of error to hook response
|
||||
context.error = err;
|
||||
self.notifyObserversOf('after ' + operation + ' error', context,
|
||||
function(_err, context) {
|
||||
if (_err && err) {
|
||||
debug(
|
||||
'Operation %j failed and "after %s error" hook returned an error too. ' +
|
||||
'Calling back with the hook error only.' +
|
||||
'\nOriginal error: %s\nHook error: %s\n',
|
||||
err.stack || err,
|
||||
_err.stack || _err
|
||||
);
|
||||
}
|
||||
callback.call(null, _err || err, context);
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Find the list of params from the callback in addition to err
|
||||
const returnedArgs = args.slice(1);
|
||||
// Set up the array of results
|
||||
|
|
|
@ -325,6 +325,86 @@ describe('async observer', function() {
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should call after operation hook on error', function(done) {
|
||||
const context = {
|
||||
req: {},
|
||||
};
|
||||
const operationError = new Error('The operation failed without result');
|
||||
let callCount = 0;
|
||||
|
||||
function fail(context, done) {
|
||||
process.nextTick(() => {
|
||||
done(operationError);
|
||||
});
|
||||
}
|
||||
|
||||
TestModel.observe('after execute error', function(ctx, next) {
|
||||
callCount++;
|
||||
next();
|
||||
});
|
||||
|
||||
TestModel.notifyObserversAround('execute', context, fail, (err, ctx) => {
|
||||
callCount.should.eql(1);
|
||||
err.message.should.eql(operationError.message);
|
||||
ctx.error.message.should.eql(operationError.message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call after operation hook on error while overwriting error', function(done) {
|
||||
const context = {
|
||||
req: {},
|
||||
};
|
||||
const operationError = new Error('The operation failed without result');
|
||||
const overwriteError = new Error('Overwriting the original error');
|
||||
let callCount = 0;
|
||||
|
||||
function fail(context, done) {
|
||||
process.nextTick(() => {
|
||||
done(operationError);
|
||||
});
|
||||
}
|
||||
|
||||
TestModel.observe('after execute error', function(ctx, next) {
|
||||
callCount++;
|
||||
next(overwriteError);
|
||||
});
|
||||
|
||||
TestModel.notifyObserversAround('execute', context, fail, (err, ctx) => {
|
||||
callCount.should.eql(1);
|
||||
err.message.should.eql(overwriteError.message);
|
||||
ctx.error.message.should.eql(operationError.message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call after operation hook on error while allowing to change err', function(done) {
|
||||
const context = {
|
||||
req: {},
|
||||
};
|
||||
const operationError = new Error('The operation failed without result');
|
||||
let callCount = 0;
|
||||
|
||||
function fail(context, done) {
|
||||
process.nextTick(() => {
|
||||
done(operationError);
|
||||
});
|
||||
}
|
||||
|
||||
TestModel.observe('after execute error', function(ctx, next) {
|
||||
callCount++;
|
||||
const err = ctx.error;
|
||||
next(err, ctx);
|
||||
});
|
||||
|
||||
TestModel.notifyObserversAround('execute', context, fail, (err, ctx) => {
|
||||
callCount.should.eql(1);
|
||||
err.message.should.eql(operationError.message);
|
||||
ctx.error.message.should.eql(operationError.message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function pushAndNext(array, value) {
|
||||
|
|
Loading…
Reference in New Issue