callifexists

A simple utility to call a function if it exists

Usage no npm install needed!

<script type="module">
  import callifexists from 'https://cdn.skypack.dev/callifexists';
</script>

README

Build Status GitHub issues Version Downloads MIT License

Intro

It's a dead simple tool for calling an optional callback function only when it is defined. Its most important use case it to call optional callback functions.

  • No dependencies
  • Well tested
  • Minimal & performant
  • Pure functions (no side effects)
  • Works in node and browser (using Webpack, Browserify or anything else that understands commonjs)
  • Works with class methods, Promise, arrow functions, ... rest parameters, eval() and new Function.

Usage

API

The API is exported with commonjs format so:

const { callIfExists, callIfFn, callIfFnThrow, isFunction, throwIfNotFunction } = require('callifexists');

callIfExists(fn, ...params)

Is just an aliwas to callIfFn!

callIfFn(fn, ...params)

Aliased to callIfExists

Calls fn passing all parameters you specified.

function sqr(x) { return x * x; }
const mult = (a, b) => a * b;
const multiplalala = 'this is not a function';
callIfFn(sqr, 3); // returns 9
callIfFn(mult, 5, 4); // 20
callIfFn(multiplalala, 5, 4); // undefined

It returns whatever the function returns. So if the function returns a Promise, it'll return that as well. If fn is not a function, undefined is returned.

const fn = Math.random() < 0.5 ? 'some string' : () => 'Stockholm';
callIfFn(fn); // may return undefined or 'Stockholm' with a 50-50 chance!

So there's no way to know if the function was defined but returned undefined or the value passed for fn was set to a non-function value. If you want, you can use callIfFnThrow πŸ‘‡ which throws if fn is not a function.

For usages of this see the documentation below.

callIfFnThrow(fn, ...params)

Same as πŸ‘† but will throw if fn is not a function.

const fn = 'Π“Ρ‘Ρ‚Π΅Π±ΠΎΡ€Π³';
callIfFn(fn); // throws Error('callIfFnThrow fn parameter was supposed to be a function but it's string')

isFunction(fn)

This is a utility function that is used internally but is useful on its own. Returns true if fn is a function (otherwise returns false).

isFunction(() => 'Alex'); // returns true
isFunction(eval); // true
isFunction(null); // false
isFunction({}); // false
isFunction(13); // false

throwIfNotFunction(fn, descriptor = 'function') {

Same as πŸ‘† but instead of returning, it'll just throw if fn is not a function. The descriptor parameter can be used to generate a more meaningful error message.

const obj = {name: 'Alex'};
throwIfNotFunction(obj, 'databaseCallback'); // throws databaseCallback was supposed to be a function but it's object`);

this

Note: the function by default will be called with the value of this for all API functions

If your function uses this there are a couple of ways to get it right.

1. Use an arrow function

Arrow functions "inherit" this from where they were defined:

this.name = 'Alex';
const myFn = () => return this.name;
callIfExists(myFn); // returns 'Alex'

2. Bind your function

Good old bind(obj) can be used to bind this in your function to an object you desire:

const obj = {
  name: 'Alex'
}
function myFn() {
  return this.name;
}
callIfExists(myFn.bind(obj)); // returns 'Alex'

3. Bind API functions

As mentioned above, the functions pass their this to your functions. So you can bind it like:

const obj = {
  name: 'Alex'
}
function myFn() {
  return this.name;
}
callIfExists.bind(obj)(myFn); // returns 'Alex'

Tests

We use mocha and chai.expect:

npm t

Lincense

MIT