“You show the world as a complete, unbroken chain, an eternal chain, linked together by cause and effect.”
― Hermann Hesse, Siddhartha
What Is Method Chaining?
If you read lots of other programmer’s code, you will likely have seen this trick. Method chaining, also called cascading is a way to simplify written code by calling function after function from an object in one continuous line.
This method will remove some unnecessary repetitions when calling multiple functions of an object in succession. Here is a snippet without using method chaining:
const drink = new Drink();
drink.addContainer('Glass');
drink.addLiquid('Water');
drink.serve();
And here is a snippet of code using method chaining:
const drink = new Drink();
drink.addContainer('Glass').addLiquid('Water').serve();
// more readable
drink.addContainer('Glass')
.addLiquid('Water')
.serve();
As you can see, there are no more repetitions when calling the functions of drink
.
Implement Method Chaining
Let’s continue using the “Drink” example. First, we have to create a class Drink
:
class Drink {
constructor(){
this.container = 'NONE';
this.liquid = 'NONE';
}
addContainer(container) {
this.container = container;
}
addLiquid(liquid) {
this.liquid = liquid;
}
serve() {
console.log("Here's a " + this.container + " of " + this.liquid + "!");
}
}
Will this work? Let’s try it:
const drink = new Drink();
drink.addContainer('glass');
drink.addLiquid('water');
drink.serve(); // "Here's a glass of water!"
drink.addContainer('Glass')
.addLiquid('Water')
.serve(); // Uncaught TypeError: Cannot read property 'addLiquid' of undefined
It works, but the method chaining does not. The error is Uncaught TypeError: Cannot read property 'addLiquid' of undefined
. addLiquid()
exists, but why is it undefined
? Let’s take a look and break the code a little:
const drink = new Drink();
const tmp = drink.addContainer('glass');
console.log(tmp); // undefined
tmp.addLiquid('water'); // Uncaught TypeError: Cannot read property 'addLiquid' of undefined
We see the same error: Uncaught TypeError: Cannot read property 'addLiquid' of undefined
. And we also see that tmp
is undefined
. So, the method chaining fails because the instance does not exist. We can fix the error by returning the instance in every function:
class Drink {
constructor(){
this.container = 'NONE';
this.liquid = 'NONE';
}
addContainer(container) {
this.container = container;
return this;
}
addLiquid(liquid) {
this.liquid = liquid;
return this;
}
serve() {
console.log("Here's a " + this.container + " of " + this.liquid + "!");
return this;
}
}
Let’s try this code again:
const drink = new Drink();
drink.addContainer('glass')
.addLiquid('water')
.serve(); // "Here's a glass of water!"
And it works successfully. To be exact, it’s executed like this:
drink.addContainer()
returns aDrink
instance, which is the same asdrink
.- The
Drink
instance calladdLiquid()
, also returning aDrink
instance which is the same asdrink
. - Lastly, the
Drink
instance returned fromaddLiquid()
callserve()
.
Conclusion
It’s quite easy, isn’t it? I use method chaining mostly to call multiple functions of the same object, but in a specific order, so my code would be easier to read. And it is not redundant.
What about asynchronous method chaining? You might want to read this article. It is an interesting idea though, but we have to do further research for that. The current known way to do this is by using Promise.then()
. But there would be lots of thens. Not so beautiful but it get the job done and easy to learn.
Thanks for reading. Let me know what you think!
Live your code and code your life!
“Break every chain of mediocrity that confines you. You may have begun at a level below average, but dare to leave that side and paddle your steps to cross the river with honours.”
― Israelmore Ayivor, Shaping the dream