cooldude101
cooldude101

Reputation: 1415

Best way to call a function before every function in an object?

I'm creating an interface and i need to run a check function before most methods, repeating the code over and over doesn't seem great. Is there a way I can run a function before a function?

Example of my current code

const uploadObject = async (object) => {
  if (!ipfs) noProvider()

  const buffer = objectToIpfsBuffer(object)
  return ipfs.add(buffer)
}

const uploadString = async (string) => {
  if (!ipfs) noProvider()

  const buffer = stringToIpfsBuffer(string)
  return ipfs.add(buffer)
}

const uploadBuffer = async (buffer) => {
  if (!ipfs) noProvider()

  return ipfs.add(buffer)
}

...

module.exports = {
  uploadObject,
  uploadString,
  uploadBuffer,
  ...
}

The function I wish to run before is if (!ipfs) noProvider()

Upvotes: 1

Views: 1922

Answers (3)

Nicholas Tower
Nicholas Tower

Reputation: 85102

I would probably just do it inline like you are, but to add another tool to your toolbelt: you could create a higher order function which takes in a function and the produces a new function that will do the check, and then do the work.

const checkIpfs = fxn => {
  return (...args) => {
    if (!ipfs) noProvider();
    return fxn(...args);
  }
}

const uploadObject = checkIpfs(async (object) => {
  const buffer = objectToIpfsBuffer(object)
  return ipfs.add(buffer);
});

const uploadString = checkIpfs(async (string) => {
  const buffer = stringToIpfsBuffer(string)
  return ipfs.add(buffer)
})

const uploadBuffer = checkIpfs(async (buffer) => {
  return ipfs.add(buffer)
})

Upvotes: 2

Trent
Trent

Reputation: 4306

I see no issue with handling this the way you are; however, another approach to "hook" a property accessor is to use a Javascript Proxy.

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

When initializing a Proxy, you'll need to provide two function inputs:

  1. target: A target object (can be any sort of object, including a native array, a function or even another proxy) to wrap with Proxy.
  2. handler: An object which is a placeholder object which contains traps for Proxy. All traps are optional. If a trap has not been defined, the default behavior is to forward the operation to the target.

Here's an example:

const handler = {
  get: function(target, prop, receiver) {
    console.log('A value has been accessed');
    return Reflect.get(...arguments);
  }
}

const state = {
  id: 1,
  name: 'Foo Bar'
}

const proxiedState = new Proxy(state, handler);

console.log(proxiedState.name);

Upvotes: 1

Mathias Silva
Mathias Silva

Reputation: 71

You could use the Proxy Object that intercepts internal operation of other object.

var newObject = new Proxy(yourObject, {
  get(target, prop, receiver){
      if(['uploadObject', 'uploadString','uploadBuffer'].includes(prop) && type(target[prop]) == typeof(Function)) {
        if (!ipfs) noProvider()
        return Reflect.get(target, prop, receiver);
      }
    },
  });

newObject.uploadObject();

Upvotes: 0

Related Questions