Proxy pattern

Proxy pattern



Information drawn from

This is a structural design pattern that behaves exactly as its name suggests. It acts as a surrogate or placeholder for another object to control access to it.

It is usually used in situations in which a target object is under constraints and may not be able to handle all its responsibilities efficiently. A proxy, in this case, usually provides the same interface to the client and adds a level of indirection to support controlled access to the target object to avoid undue pressure on it.

The proxy pattern can be very useful when working with network request-heavy applications to avoid unnecessary or redundant network requests.

In this example, we will use two new ES6 features, Proxy and Reflect.:

Now, we create a function that can be thought of as a network request. We named it as networkFetch. It accepts a URL and responds accordingly. We want to implement a proxy where we only get the response from the network if it is not available in our cache. Otherwise, we just return a response from the cache.

The cache global variable will store our cached responses. We create a proxy named proxiedNetworkFetch with our original networkFetch as the targetand use apply method in our handler object to proxy the function invocation. The apply method gets passed on the target object itself. This value as thisArg and the arguments are passed to it in an array-like structure args.

We check if the passed url argument is in the cache. If it exists in the cache, we return the response from there, never invoking the original target function. If it does not, then we use the Reflect.apply method to invoke the targetfunction with thisArg (although it’s not of any significance in our case here) and the arguments it passed.

// Target
function networkFetch(url) {
  return `${url} - Response from network`;
}

// Proxy
// ES6 Proxy API = new Proxy(target, handler);
const cache = [];
const proxiedNetworkFetch = new Proxy(networkFetch, {
  apply(target, thisArg, args) {
    const urlParam = args[0];
    if (cache.includes(urlParam)) {
      return `${urlParam} - Response from cache`;
    } else {
      cache.push(urlParam);
      return Reflect.apply(target, thisArg, args);
    }
  },
});

// usage
console.log(proxiedNetworkFetch('dogPic.jpg')); // 'dogPic.jpg - Response from network'
console.log(proxiedNetworkFetch('dogPic.jpg')); // 'dogPic.jpg - Response from cache'

------------------------------------------------------------------------

Last update on 04 Feb 2020

---