Use Cases for IIFEs
Tags: javascript, typescript, webdev, tutorial
Published: 2023-09-13 06:33:18

First, I'd like to lead this article with a confession:  

Whenever I'm presented with a programming concept, I immediately start searching my brain for practical ways that I would _use_ that concept.  If I can't think of a practical application for that concept, I might technically "understand" it - but I'll never truly _master_ it.

This can be a bit of a mental roadblock for me because someone says, "Hey, you should consider using [INSERT CONCEPT HERE]," and I nod and read a few basic articles about the concept.  But unless I can envision a logical scenario where I'll _use_ that concept, it just sits in the back of my brain, gathering dust, and doing me little good in daily programming endeavors.

For many years, the Immediately Invoked Function Expression (IIFE) was exactly this type of concept.  Sure, I understood what an IIFE _was_.  But they never really "clicked" for me because there was never any time when I thought, "Oh, wait.  I should use an IIFE here!"

For whatever reason, I've actually started using IIFEs recently with some regularity.  So I figured I'd write up this article because it might help others who've never really grasped their utility.
<br/><br/>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8k7feqc3wgxba5v9vnb1.jpg)
## What is an IIFE?
The fully-articulated name of an IIFE basically tells you what it is.  It's a function expression that's... immediately invoked.  It differs from an _anonymous_ function in that anonymous functions can still be called numerous times, like this:

```javascript
[1,2,3].forEach(item => console.log(item))
```

In the example above, this is the _anonymous_ function:

```javascript
item => console.log(item)
```

It's "anonymous" because it's not stored in a variable.  So it has no "handle" that we can use to manually call the function at other points in our code.  But it's not an _immediately invoked function expression_ because it's not run... _immediately_.  Instead, it is run once for each item that's passed into the Array prototype function `.forEach()`.

IIFEs have a special syntax that tells the JavaScript engine to run the logic inside them _immediately after they're defined_.  That syntax looks like this:

```javascript
const item = 1;
(() => console.log(item))()
```

In the example above, the IIFE will console-log the value of `item` (`1`).  And that's fine, except...  When I look at an example like the one shown above, the IIFE just feels utterly... pointless.  I mean, if all you want to do is console-log the value of `item`, then why wouldn't you just do this?

```javascript
const item = 1;
console.log(item);
```

Of course, for this (totally simplistic) example, there really is no logical reason to use an IIFE.  And it's that basic bit of common sense that always led me to write off IIFEs as a near-pointless language construct.

To be clear, I've occasionally encountered IIFEs that were written by _other_ devs.  But sooooo many times, when I see IIFEs "in the wild", I still end up scratching my head as to why the original developer even chose to use it in the first place.  My thinking went like this:

1. IIFEs are just a block of _immediately-invoked_ code.<br/>

2. So if I want that code to be _immediately-invoked_, then why wouldn't I simply... write the code - without wrapping it inside an IIFE???

But as I stated above, I've found several scenarios where they can truly be useful.  I hope that the following examples will help you to grasp their utility as they have for me.
<br/><br/>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bth2h1zv0bi8ipoay67t.jpg)
## Libraries
Let's say that you have a single file that contains a "library" of utility functions.  That may look something like this:

```javascript
// conversionUtilities.js
const convertUserDBToUI = userDB => {
  return {
    id: userDB.user_id,
    firstName: userDB.first_name,
    lastName: userDB.last_name,
  }
}

const convertUserUIToDB = userUI => {
  return {
    user_id: userUI.id,
    first_name: userUI.firstName,
    last_name: userUI.lastName,
  }
}
```

The functions above simply take objects that are formatted for the UI and converts them into objects that are formatted for the DB (and vice versa).  

Of course, if these are truly meant to be "utility" functions (meaning that you'll probably need to call on them from various places throughout your application), you'll need to `export` these functions so they can be imported at other places in the app.  That would look like this:

```javascript
// conversionUtilities.js
export const convertUserDBToUI = userDB => {
  return {
    id: userDB.user_id,
    firstName: userDB.first_name,
    lastName: userDB.last_name,
  }
}

export const convertUserUIToDB = userUI => {
  return {
    user_id: userUI.id,
    first_name: userUI.firstName,
    last_name: userUI.lastName,
  }
}
```

The code above would work just fine.  However, it may lead to some extraneous `import` statements throughout your code, because anytime you need to use two-or-more of these functions in a single file, you'll need to include two-or-more `import` statements in those files.  When you're creating "library" files that contain many related _utility_ functions, it can often be useful to have them contained within a single `export`.

One way you could accomplish this is with a `class`:

```javascript
// conversionUtilities.js
export const Convert = class {
  userDBToUI(userDB) {
    return {
      id: userDB.user_id,
      firstName: userDB.first_name,
      lastName: userDB.last_name,
    }
  }

  userUIToDB(userUI) {
    return {
      user_id: userUI.id,
      first_name: userUI.firstName,
      last_name: userUI.lastName,
    }
  }
}
```

Once again, the code above works just fine.  Here are some benefits of the above code:

1. We no longer need to repeat `convert` in every one of the method names, because it's implied in the name of the class.<br/>

1. All of our utility functions are "bundled" inside a single entity - the `Convert` class - so they don't need to be imported individually.<br/>

But there are also a few "downsides":

1. Some (nay... _many_) JS/TS developers simply abhor using the `class` keyword.<br/>

1. Anytime you need to use these utility functions, you first need to call something like `const convert = new Convert();` before using the utility functions like `const userUI = convert.userDBToUI(userDB);`.  That could become... cumbersome.<br/>

You could solve the second "problem" by exporting an _instance_ of the class, rather than exporting the class itself.  That would look like this:

```javascript
// conversionUtilities.js
const Convert = class {
  userDBToUI(userDB) {
    return {
      id: userDB.user_id,
      firstName: userDB.first_name,
      lastName: userDB.last_name,
    }
  }

  userUIToDB(userUI) {
    return {
      user_id: userUI.id,
      first_name: userUI.firstName,
      last_name: userUI.lastName,
    }
  }
}

export const convert = new Convert();
```

That saves us some keystrokes whenever we're importing the `Convert` class.  But it still rubs some devs the wrong way because we're relying on classes.  But that's OK.  Because we can accomplish the same thing with a function:

```javascript
// conversionUtilities.js
export const Convert = () => {
  const userDBToUI = userDB => {
    return {
      id: userDB.user_id,
      firstName: userDB.first_name,
      lastName: userDB.last_name,
    }
  }

  const userUIToDB = userUI => {
    return {
      user_id: userUI.id,
      first_name: userUI.firstName,
      last_name: userUI.lastName,
    }
  }

  return {
    userDBToUI,
    userUIToDB,
  }
}
```

Here are the benefits of this approach:

1. No more "yucky" `class` keyword.<br/>

1. Again, we no longer need to repeat `convert` in every one of the function names, because it's implied in the name of the exported function.<br/>

1. All of our utility functions are "bundled" inside a single entity - the `convert` function - so they don't need to be imported individually.<br/>

But there's still at least one "downside":

1. Anytime you need to use these utility functions, you first need to call something like `const convert = Convert();` before using the utility functions like `const userUI = convert.userDBToUI(userDB);`.  That could become... cumbersome.<br/>

You could solve this "problem" by exporting the _invocation_ of the parent function, rather than exporting the parent function itself.  That would look like this:

```javascript
// conversionUtilities.js
const Convert = () => {
  const userDBToUI = userDB => {
    return {
      id: userDB.user_id,
      firstName: userDB.first_name,
      lastName: userDB.last_name,
    }
  }

  const userUIToDB = userUI => {
    return {
      user_id: userUI.id,
      first_name: userUI.firstName,
      last_name: userUI.lastName,
    }
  }

  return {
    userDBToUI,
    userUIToDB,
  }
}

export const convert = Convert();
```

Honestly, this is the primary way that I usually see this done.  But there is another way - with an IIFE - that we could do this without having to first 1) define the `Convert` function, and then 2) export the invocation of that function.  That would look like this:

```javascript
// conversionUtilities.js
export const convert = (() => {
  const userDBToUI = userDB => {
    return {
      id: userDB.user_id,
      firstName: userDB.first_name,
      lastName: userDB.last_name,
    }
  }

  const userUIToDB = userUI => {
    return {
      user_id: userUI.id,
      first_name: userUI.firstName,
      last_name: userUI.lastName,
    }
  }

  return {
    userDBToUI,
    userUIToDB,
  }
})()
```

Notice here that we didn't have to define the parent function, and then export _the invocation of that function_.  Instead, we used an IIFE to do it all in one statement.  Now, whenever someone imports `convert`, they'll get an object that already contains all of the utility functions inside `convert`.

Is this some rock-solid no-brainer use case for IIFEs???  No.  As stated above, you can accomplish the same thing by:

1. Exporting every single utility function individually.<br/>

1. Encompassing the utility functions inside a class, and then exporting an instance of that class.<br/>

1. Encompassing the utility functions inside a parent function, and then exporting the invocation of that function.<br/>

Nevertheless, I find the IIFE approach to be just _a little bit_ cleaner.  And it's at least _one_ valid use case for IIFEs.<br/><br/>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zuuefqh9y7qgdh3xvihp.jpg)
## Swallowing Promises
Async/await can be powerful tools when dealing with data calls and other asynchronous actions.  But they can also cause a bit of a cascading headache in your code - especially in strict TypeScript code.

`await` can only be used inside an `async` function.  Imagine that you have three cascading functions that do the following:

1. FunctionA handles the result of a user action (like clicking a "Submit" button).<br/>

1. If the right conditions are met, FunctionA then calls some validation logic in FunctionB.<br/>

1. Based on the results of the validation, FunctionB may then call FunctionC, which transmits the data to the server via an asynchronous REST call.<br/>

You want to use the `await` syntax in FunctionC, which means that you need to define it as an `async` function.  

But this means that FunctionB will now be expecting _a promise_ from FunctionC.  So... you change FunctionB to be an `async` function.

But that means that FunctionA will now be expecting _a promise_ from FunctionB.  So... you change FunctionA to be an `async` function.

But now the event handler that originally called FunctionA is also expecting _a promise_.  And depending on how strict your TypeScript environment is configured, that simply may not be an option.

The "cascading" effect of `async/await` would look something like this:

```typescript
export const App = () => {
  const submit = () => {
    const result = await someApiCall(values);
    // handle API result
    return result;
  }

  const doValidation = () => {
    // check some validation
    if (isValid) {
      return submit();
    }
  }

  const handleSubmit = () => {
    // set some state vars
    if (someCondition) {
      return doValidation();
    }
  }

  return <>
    <button onClick={handleSubmit}>
      Submit
    </button>
  </>
}
```

In the example above, the TypeScript compiler will start complaining because `callApi()` is not an `async` function.  So you set `callApi()` to be `async` but... that also requires `doValidation()` to be `async`.  So you set `doValidation()` to be `async` but... that also requires `handleSubmit()` to be `async`.  So you set `handleSubmit()` to be `async` but... TypeScript might _still_ complain because the `onClick` event handler is not configured to handle the resulting promise.

At this point, you've started to shove `async` into a lot of places where you really never wanted it to be.  And to make it even worse, TypeScript will _still_ complain about the fact that your `onClick` handler is not handling the resulting promise.

[NOTE: In plain ol' vanilla JavaScript, you can simply _ignore_ the resulting promise.  But you can't convert your entire project from TypeScript to JavaScript just because you don't wanna deal with all of these cascading usages of `async/await`.]

Luckily, an IIFE can do a load of good here.  That would look like this:

```typescript
export const App = () => {
  const callApi = () => {
    (async () => {
      const result = await someApiCall(values);
      // handle API result
      return result;
    })()
  }

  const doValidation = () => {
    // check some validation
    if (isValid) {
      return callApi();
    }
  }

  const handleSubmit = () => {
    // set some state vars
    if (someCondition) {
      return doValidation();
    }
  }

  return <>
    <button onClick={handleSubmit}>
      Submit
    </button>
  </>
}
```

In the code above, we can now use `async/await` inside `callApi()` _without ever having to declare `callApi()` as an `async` function_.  This works because the asynchronous call _is_ happening inside an `async` function.  It just so happens that the `async` function is... an IIFE _inside the `callApi()` function_.  

This is actually a use case for IIFEs that I use _a lot_.<br/><br/>


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3b75mu8f0rcdtkl1w92f.png)
## In-place Logic
Finally, I wanna illustrate a scenario where _in-place logic_ (i.e., the kind of logic that's provided by an IIFE) can make a lot of sense.

I've recently been helping a friend with a bunch of EDI data transformations.  On the surface, the work is pretty simple.  You get a big data object that's supposed to be in a given format - maybe something like this:

```javascript
const rawData = {
  fee: 'fee',
  einz: '1',
  fie: 'fie',
  zwei: '2',
  foe: 'foe',
  drei: '3',
  fum: 'fum',
}
```

Then you have to write some transformation routine that will extract (and "massage") certain values and return a new data object in a different format, like this:

```javascript
const getGiantSpeak = data => {
  return {
    fee: data.fee,
    fie: data.fie,
    foe: data.foe,
    fum: data.fum,
  }
}
```

The "problem" arises when you realize that many of the vendors supplying the data will _format_ that data in many different ways.  For example, the simple logic above works just fine as long as you assume that the values in `rawData` are simple scalar values.  

But then you find that your data transformations are intermittently failing.  When you investigate the intermittent problems, you realize that _sometimes_ the vendor is submitting `rawData.fie` as a simple string.  And _other times_ they're submitting it as an _array of strings_.  So to fix this, you need to insert a little bit of logic at the point where `getGiantSpeak()` is returning the `fie` value.

In this scenario, I find that a simple IIFE works wonders:

```javascript
const rawData = {
  fee: 'fee',
  einz: '1',
  fie: ['fie', 'fiddler'],
  zwei: '2',
  foe: 'foe',
  drei: '3',
  fum: 'fum',
}

const getGiantSpeak = data => {
  return {
    fee: data.fee,
    fie: (() => {
      if (Array.isArray(data.fie))
        return data.fie.join(',');
      else 
        return data.fie;
    })(),
    foe: data.foe,
    fum: data.fum,
  }
}
```

[NOTE: I realize that you can also accomplish the above logic with a simple ternary operator.  But the "real life" examples usually require some more "nuanced" logic that doesn't lend itself to a ternary operator.]

In this scenario, the logic needed to build the new object is truly _single-use_, and it can be much cleaner to encompass it in an IIFE.