mgechev / aspect.js

JavaScript library for aspect-oriented programming using modern syntax.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

onThrowLogger doesn't handle async exceptions

olgeorge opened this issue · comments

First of all, thanks for addressing the cross-cutting concerns problem in JS, much appreciate the amazing work.

Here's my code:

const { beforeMethod, afterMethod, onThrowOfMethod, Wove } = require('aspect.js');

class LoggerAspect {
    @beforeMethod({
        methodNamePattern: /.*/,
        classNamePattern: /.*/
    })
    beforeLogger(meta, ...args) {
        console.log(`Starting method ${meta.method.name} with arguments: ${args.join(', ')}`);
    }
    @afterMethod({
        methodNamePattern: /.*/,
        classNamePattern: /.*/
    })
    afterLogger(meta, ...args) {
        console.log(`Successfully completed method ${meta.method.name} with arguments: ${args.join(', ')}`);
    }
    @onThrowOfMethod({
        methodNamePattern: /.*/,
        classNamePattern: /.*/
    })
    onThrowLogger(meta, ...args) {
        console.log(`Error during the invocation of method ${meta.method.name} with arguments: ${args.join(', ')}`);
        console.log('Exception: ', meta.method.exception);
    }
}

@Wove({ bar: 42 })
class MyClass {
    myMethodX(x) {
        console.log(`myMethodX: ${x}.`);
        throw "Catching from myMethodX successfully";
    }
    async myMethodY(y) {
        console.log(`myMethodY: ${y}.`);
        throw "This exception from async myMethodY is not caught and not logged!";
        //return await Promise.reject("This will throw an exception that won't be caught or logged either!");
        //return Promise.reject("This rejection won't be caught or logged either!");
    }
}

const o = new MyClass()

console.log("Will invoke myMethodX with xxx");
o.myMethodX("xxx")
console.log("Will invoke myMethodY with yyy");
o.myMethodY("yyy")

Here's the output:

Will invoke myMethodX with xxx
Starting method myMethodX with arguments: xxx
myMethodX: xxx.
Error during the invocation of method myMethodX with arguments: xxx
Exception:  Catching from myMethodX successfully
Will invoke myMethodY with yyy
Starting method myMethodY with arguments: yyy
myMethodY: yyy.
Successfully completed method myMethodY with arguments: yyy

/usr/local/lib/node_modules/serverless/lib/classes/Error.js:93
    throw new Error(e);
    ^

Error: This exception from async myMethodY is not caught and not logged!
    at module.exports.logError (/usr/local/lib/node_modules/serverless/lib/classes/Error.js:93:11)
    at process.on (/usr/local/lib/node_modules/serverless/bin/serverless:12:41)
    at emitTwo (events.js:106:13)
    at process.emit (events.js:194:7)
    at emitPendingUnhandledRejections (internal/process/promises.js:85:22)
    at runMicrotasksCallback (internal/process/next_tick.js:67:9)
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)

The exception in the async method is not caught, instead the following log line is produced:
Successfully completed method myMethodY with arguments: yyy

Is this a bug or a feature?

Currently aspect.js supports only sync targets. This means that before, after and around will not work properly with async methods as well.

It shouldn't be hard to implement support for async advices in similar fashion. Lets keep the issue open. I'll be happy to review & merge a PR implementing the feature.

Alright, I might look into this later. Thanks!

@olgeorge this seems to solve the issue you have.