Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS TS decorator to conditionally prevent method execution

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)
    }
}
like image 300
Chris Avatar asked Dec 03 '17 16:12

Chris


1 Answers

1. 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
like image 92
Christian Santos Avatar answered Sep 25 '22 07:09

Christian Santos