Skip to main content
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Brian Ghidinelli
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Brian Ghidinelli ( @ghidinelli )

Using An Immediately Invoked Function Expression (IIFE) And CachedWithin To Easily Cache Steps In A Procedural Script In Lucee 5.3.2.77

By on
Tags:

As I've demonstrated before, the cachedWithin function memoization feature can be applied to Closures in Lucee 5.3.2.77. I've also demonstrated that Immediately Invoked Function Expressions (IIFE) work In Lucee. These two features can be combined to easily cache steps in a procedural script without too much additional ceremony. And, while I probably wouldn't use this technique in a production application, this can be quite handy for small, one-off utility scripts that I write in my local development environment.

I used this feature just the other day when I was trying to locate LaunchDarkly feautre flags in my code-base. I did this using a utility script that made an API call to LaunchDarkly to retrieve feature flags; and then, I scoured the local file system, looking for references to those feature flags.

This script had two high-level aspects:

  1. Getting the remote feature-flags and scanning the local file-system.
  2. Rendering the results of this reconciliation.

Once I had the first part working, I didn't want to constantly be re-calculating the results while I was fine-tuning the rendering of said results. As such, I wrapped the first part in an IIFE and cached it. This way, when I refreshed the page, the only work that Lucee was doing was the rendering of the cached results.

To see how this can work, I created a simple demo that randomly sorts the letters in a string. This is intended to represent "hard work"; and, is being calculated and cached within an immediately invoked function expression:

<cfscript>

	someData = "Hello World!";

	// Imagine that this step of the "procedure script" is a bit more intensive to
	// calculate. As such, we can easily cache this step without too much ceremony by
	// wrapping it in an Immediately Invoked Function Expression (IIFE) that makes use
	// of the cachedWithin function memoization feature.
	transformedData = (function() cachedWithin = createTimeSpan( 0, 1, 0, 0 ) {

		var letters = someData.reMatch( "." );

		// Randomly sort the letters in the data.
		letters.sort( () => randRange( -1, 1 ) );

		return( letters.toList( "" ) );

	})();

	echo( transformedData );

</cfscript>

As you can see, I'm using an IIFE (()=>{})() in conjunction with the cachedWithin memoization to cache the transformation of data within the procedure script. This essentially caches a step in the algorithm without having to break the process out into a UDF (User Defined Function) or extract it into a ColdFusion Component (CFC).

And, when we run the above Lucee CFML, we get the following output:

HellWlor!od

And, if we run this page again. We get the same output since it is cached by the Lucee ColdFusion application for an hour.

Obviously, there are "smarter" ways to do this. I could have created a clean abstraction that implemented caching; I could have stored the value in an application variable; heck, I could have even broken this procedure up into two steps that generated an intermediary JSON file (which was my first approach). But, this was a small utility script. I wasn't going for "smart"; I was going for "effective." And, it turns out that using an IFFE to cache a value during the development process is quite effective.

So, again, I probably wouldn't use something like this in Production. But, locally, this is a nice little "trick" to speed up the ColdFusion development process when refreshing the page doesn't need to incur the overhead of complex processing.

Want to use code from this post? Check out the license.

Reader Comments

9 Comments

Thanks Ben, IIFE is very interesting!
This code does not work with CF2018, is it possible to have it compatible for both (Lucee / CF)?

15,674 Comments

@Paolo,

I am not sure that you can make it Adobe ColdFusion compatible because it is leveraging a feature that I believe is Lucee CFML specific; namely, the ability to set a cachedWithin attribute on a Function.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel