I would like to write a method decorator that conditionally prevents the execution the method or to replace the method with some other procedure. In particular I want different behavior based on when it is called on the client or on the server:
function serverMethod(target) {
if(Meteor.isClient) {
// call server method to delete a user
// prevent execution of decorated method
}
}
class User {
@serverMethod
delete() {
UserCollection.delete(this.id)
}
}
I would like to write a method decorator that conditionally prevents the execution the method or to replace the method with some other procedure. In particular I want different behavior based on when it is called on the client or on the server:
function serverMethod(target) {
if(Meteor.isClient) {
// call server method to delete a user
// prevent execution of decorated method
}
}
class User {
@serverMethod
delete() {
UserCollection.delete(this.id)
}
}
Share
Improve this question
asked Dec 3, 2017 at 16:55
ChrisChris
14.2k23 gold badges93 silver badges181 bronze badges
1 Answer
Reset to default 221. Conceptual Overview
ES2016 Method Decorators are functions that have 3 parameters:
target
— either the prototype of the class (if the method being decorated is an instance method) or the constructor of the class (if the method being decorated is static).name
— the name of the method being decorated.descriptor
— the [descriptor object][1] of the method being decorated.
A decorator can decorate (or enhance) a method by wrapping the existing method around a new function that does more (or fewer) things than the original function.
2. Fixing/Improving the Question's Code
With this in mind, serverMethod
should wrap the descriptor.value
(which contains the method that we want to decorate) around a new function that checks whether we are in the client or server:
function serverMethod(
target: any,
name: string,
descriptor: PropertyDescriptor
) {
const method = descriptor.value; // references the method being decorated
descriptor.value = function (...args) {
if (Meteor.isClient) return; // exit the function
// This part will run when Meteor.isClient == false
method.apply(this, args);
};
}
class User {
@serverMethod
delete() {
UserCollection.delete(this.id);
}
}
It's important not to forget the ...args
, so that the arguments passed to your methods will also be used by the decorated method via method.apply
.
3. Further reading
- JS Decorator Design
- JS Spec Proposal
- Method Decorators in TS