Shruggie
Shruggie

Reputation: 938

Wrapping JavaScript functions that have properties

I'm trying to wrap the request node module to add a log statement for every request. Normally this is pretty straight forward:

function wrapper(...args) {
  console.log('Hello');
  return request(...args);
};

However, the request function has properties such as request.defaults that I also need. How might one wrap only the function but keep the properties, without changing the request API?

Upvotes: 2

Views: 687

Answers (2)

Christian Santos
Christian Santos

Reputation: 5456

Here are two ideas for wrapping an existing function while keeping the properties of the function being wrapped:

Copy properties to new function

First, we create a new function that wraps request. Then, we use Object.assign() to copy properties from request to wrappedRequest:

function wrappedRequest(...args) {
    console.log('called request!');
    return request(...args);
};

Object.assign(wrappedRequest, request); // copy properties from request to wrappedRequest

The thing to keep in mind here is that you are only copying the properties once. Any properties that are modified or added after this statement will not be added to your new function.


ES2015 Proxy()

This is the preferred way if it's available. It allows you to capture function calls, property getters, and property setters, even if they are set after the proxy is created:

const handler = {
    apply: function(target, thisArg, argumentList) {
        console.log('called request!');
        return target.apply(thisArg, argumentList);
    },
};

const wrappedRequest = new Proxy(request, handler);

The handler.apply() intercepts any calls to wrappedRequest(). And by default, getting and setting properties on the proxy will mirror getting and setting properties on the target object, which in this case is request.


Further Reading

Upvotes: 0

Charlie
Charlie

Reputation: 23798

Probably you should return the request function itself without executing it -

function wrapper() {
   console.log('logs');
   return request;
}


wrapper()('http://sample.com', (err, rsp, body) => {

   //do something
})

wrapper().defaults({});    //calling the default method

Upvotes: 1

Related Questions