The benefit of the Thenable object in JavaScript
The relation between thenable
object, promise
and async/await

If you use libraries like mongoose
, knex
and some others similar to them — which has kind of chainable methods and also runs asynchronously — you should read this article too.
You might have already heard about thenable
object, promise
and async/await
. If you haven’t or still didn’t get the relation between them, don’t worry we will cover that here completely.
What is “thenable” object?
The definition of thenable
object is the simplest thing in the world:
Any object that has a method named “
then”
is called a “thenable” object.
For Example:
This object (obj
) is a thenable
object.
Note: A thenable
object is allowed to have any other property and method with any name as well, but it must have a method is named then
to be a thenable
object.
The relation between “thenable” object and “promise”?
Simply every promise
object is just a thenable
object, because it has a then
method (which is used to access the result of a settled promise
). That’s it.
But keep in mind that this relation is not the other way around, which means that every thenable
object is not a promise
object.
The relation between “thenable”, “promise” and “async/await”
The then
keyword is just a convention that has been defined to make life easier.
For instance, now we all know to access the result of a promise, we should call the then
method of it. The name is not exec
, run
, get
, map
or anything else that causes confusion.
This naming convention has also helped us to have async/await
syntax in JavaScript. But how?
Look that the code below and see the magic:
If you are not familiar with IIFE function check this article.
You probably have already used async/await
syntax in your codes and know how to used it.
But do you also aware that how async/await
works?
We are not going to fully cover the behind of the scene of async/await
here. However, if you are curious about it (and you should be), you can check this article out to get the main idea of how it works.
Brief explanation of how “async/await”
works
You should know that whenever you put an await
keyword before any function (object), JavaScript just tries to call the then
method of that object.
Also because async/await
syntax is implemented by generator
function and await
keyword is exactly used instead of yield
keyword, so the async
function needs to be resumed after calling the then
method. In order to handle this operation, async
function also sends a callback to the then
method as a parameter that contains the functionality for resuming itself.
I know it sounds a little bit fuzzy and for getting the idea better, you should check out this sample code:
You can run this code and see the result yourself.
If you look at the output, you can see that almost everything works as expected. But we still don’t have the result of the last console.log(‘end’)
and the operation is kind of freezing in that point.
The reason of this freezing is because the callback function which has been sent to the then
method has not been called yet to resuming the async
function.
In order to solve the problem, we should just call the callback to continue the operation.
Also if you send any value to the callback as its parameter, you will get it by the await
keyword (see the code below):
And now everything worked perfectly.
Main subject
I guess till here you got the idea of what we are talking about and you might find out that how mongoose
, knex
and some other libraries work with some tweaking the code.
As a reminder, these libraries can be chainable and whenever you put an await
keyword in behind of them or call the then
method in their chain, they work exactly like a promise
object.
In the following we are intending to walk through a simple example of a chainable object that would be ran by await
keyword and/or then
method.
The functionality that we expect from this stupid example that we are going to implement is to have some simple math methods (i.e. add
, sub
, mul
, div
) and whenever we use it with await
keyword, it would run the main asynchronous operation and returns the corresponding result (which can be fulfilled
or rejection
).
The main asynchronous operation would be fulfilled if the reminder of the final value is divided by 2 be greater than zero — or not equal to zero (n % 2 !== 0
) — and otherwise it would be rejected.
Now we have an asynchronous function, let’s implement another simple function which can be chainable.
Note: I just refuse to use
this
keyword here to avoid confusion that some people might have with it.
Now this function (mathOp
) can be used in this way:
It’s time to get to the main point and add the magical then
method to this chainable object and run the asyncFunction
inside of it. Afterward just return the result of it (which is a promise
object).
Reminder: Don’t forget the callback function is going to be sent by await
keyword automatically.
This is the whole implementation of the then
method. It is simple, isn’t it?
Let’s put it inside the op
object:
And now you can run the code below to see the result:
Up until now it sounds that it works perfectly, but let me remind you that we didn’t handle the error that is caused by the rejection
state of the asyncFunction
.
First of all, to handle the errors, we need a catch
method beside of the then
method as well.
Put this method next to then
method inside of op
object.
There is nothing special about catch
method and we just added it that we could use it on chaining methods ourselves — which works like then
method on chaining and also send the callback to the catch
method on the returned promise
object.
In the next step for handling errors we need to tweak our then
method.
If you wonder why we need to change the then
method to handle the errors and what is the relation between them, let me tell you another secret of async/await
.
I have to admit that I already lied to you about that await
keyword that I said it just sends one callback on calling the then
method, I’m sorry about that guys, because it sends two callbacks.
As a reminder we should mention that the then
method on promise
object takes two callbacks, but the second one is arbitrary which is used as a callback for catching errors — just like catch
method.
If you are curious about how promise
works, you should check out this book.
If you change the then
method body like the code below, you would see the same output as below:
Great! Now we can also use mathOp
function with await
keyword inside of a try/catch
block to handle the errors.
We are done with handling errors and the whole functionality of our stupid example.
At the end we can also do some fancy stuff to have a little cleaner code.
Wrapping up
I hope you found this article useful.
If there is any unclear or ambiguous part, please feel free to ask your questions in the comment section or you can send me message directly.