The lodash _.once method use examples.

Part of my debugging process involves placing a console.log in my code at some point to log out to the console the status of some value. Often it might be placed in the body of some code that ends up getting called often, and as such it will get logged to the console a whole bunch of times real fast. So for this reason, along with many others this might not always be the best solution for debugging.

So when it comes to getting into situations where something is being logged to the console to fast this is where using something like the _.once in lodash can be helpful when working on a project that uses lodash as part of it’s code base. The method will return a new function that will call a given function only once when called, and any additional calls after that will not call the given function as an argument.

It is also not so hard to create a vanilla javaScript once method also, and if you have not done so at any time thus far I would say that it is a good idea to do so if you are still somewhat new to javaScript. A once method is a good, simple example of closure in javaScript.

1 - Basic use example of _.once in lodash

The lodash _.once method works by returning a function that will call the given function only once when called. Any additionally calls to the function will result in nothing happening.

1
2
3
4
5
6
7
8
9
var trap = _.once(function(mess){
console.log(mess);
});
trap('okay'); // 'okay' logged to the console
trap('nope'); // ( nothing )

So the lodash once method can come in handy when I want to log something to the console just once and only once inside a loop of some kind. That being said the lodash once method can come in handy as a kind of debugging tool.

2 - How _.once works

If you have some experience with concept of closures, and guessed that is how _.once works then you would be right.

I often like to study the source code of very popular javaScript projects in oder to have at least some understanding as to how it works, as such the source code of _.once in v4.17.4 of lodash looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function before(n, func) {
var result;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
n = toInteger(n);
return function() {
if (--n > 0) {
result = func.apply(this, arguments);
}
if (n <= 1) {
func = undefined;
}
return result;
};
}
function once(func){
return before(2,func);
}

So the _.once method is a good example of how closures come in handy. Once returns a function within a function, and the value of result in the before helper is what gets returned each time _.once is called.

3 - The nature of what is returned.

When it comes to whatever is returned with the method that is given to _.once, the same value will be given each time it is called after it has been called once. The method given will never be called again, but the value returned when it was called will be returned each time.

1
2
3
4
5
6
7
8
var grab = _.once(function(val){
return val;
});
console.log(grab(42)); // 42
console.log(grab(43)); // 42

4- Be mindful of references when dealing with objects

There is still the matter of objects being references in javaScript though. This is why we have methods like _.cone in lodash.

1
2
3
4
5
6
7
8
9
var obj = {x:41};
obj.x += 1;
console.log(grab(obj)); // {x:42}
obj.x += 1;
console.log(grab(obj)); // {x:43}

No problem it’s a simple fix.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var grab = _.once(function(val){
return _.clone(val);
});
var obj = {x:41};
obj.x += 1;
console.log(grab(obj)); // {x:42}
obj.x += 1;
console.log(grab(obj)); // {x:42}

5 - Using _.once in a loop

As I mention earlier _.once comes in handy when I am working with some kind of project that involves one or more instances of something like setTimeout, or requestAnimationFrame going on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var hold = _.once(function(obj){
// I want a shallow copy of the given object
// and not a reference so _.clone it
return _.clone(obj);
});
var values = {
x: 0,
dx: 5
};
var loop = function(){
values.x += values.dx;
// because hold was made with _.once
// hold with log {x:5,dx:5} on each tick
console.log( hold(values) );
// if I just use console.log
// I get the latest values on each tick
console.log(values);
setTimeout(loop, 1000);
};
loop();

6 - Vanilla javaScript Once method

Writing a vanilla javaScript once method is not that hard at all. If you have a basic understanding of closures in JavaScript slapping together a vanilla ajvaScript alternative to the lodash once method is a snap. Just have a function that returns a function and inside the body of that inner function call a method that is given as an argument of the outer function, and change the state of a variable that is in the body of the outer function that is used to find out if the function should be called or not with a conditional statement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let once = (func) => {
let calls = 1;
return function(){
if (calls > 0) {
func.apply(null, arguments);
calls--;
}
};
};
let trap = once((mess) => {
console.log(mess);
});
trap('okay'); // 'okay' logged to the console
trap('nope'); // (nothing)

7 - Conclusion

The _.once method is a great example of closures in action. For me it was also a great experience to look into the source code of lodash to find that many of these methods work very much the same way as if I was to take the time the write them myself. With that said it is not so hard to create my own log once method, maybe there is a bot more to it when it comes to making a simple utility module that will work well in both a nodejs and browser environment though. With that said I have made a javaScript example that is a utility module that contains custom logging methods, including a create log once method.