Async JS Patterns using Thunks
Published: 2022-02-01 14:14:47

This is the second part of the series Async JS Patterns, in the previous post I wrote about callbacks and how they help us to sort some common programming puzzles such as concurrency. In this post we will talk about a slightly different approach of callbacks, thunks.

Let’s first revise an important concept behind thunks. 

> A **closure** is the combination of a function enclosed with references to its surrounding state (the **lexical environment**). [MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Closures)

Let’s check the example provided by MDN, (I intentionally changed some comments and lines for a better understanding).

```jsx
function makeFunc() {
    var name = 'Mozilla';
    function displayName() {
        console.info(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();   
// it executes the function displayName() 
// using all the private state (in this case the string) 
// from its parent function makeFunc()
```

As we can see in the previous snippet, a closure lets a function remembers the collection of states (similar to a conventional memory system) and play with them, it is very simple but applied in async tasks makes it very interesting. 

Practical speaking a thunk is the **returned function** in a function, like in the next code:

```jsx
function helloWorld() {
// Some private state
    return function thunk(cb){
				// We have access to all private state from helloWorld() - closure -
				// And aditionally we can use it as a mechanism for delaying execution
				// (check the comments at the end of this example)
				cb()
    }
}

let th = helloWorld()
th(cb) 
// Whenever the function helloWorld() has finished its instructions,
// we pass to the return function a callback with more instructions,
// resulting in a sequential flow!
```

The previous example is a taste of async thunks but let’s keep it simple, we will dig into async thunks in a while.

Technically speaking a thunk is a container around a collection of state, it is a function that returns an other function thus it has access to the parent private state (closure).  

Let’s consider the next synchronous thunk:

```jsx
function sumThunk(a, b) {
    return a+b
}

function commonFunction(){
    const a = 10 
    const b = 10  
    return sumThunk(a,b) //This returns a thunk function that make use of the parent private state, 
                         // everytime it is called, it will always remember this state.
                         // It acts like a container around a value(s), pretty similar to a token
}

const total = commonFunction()
console.info(total) // 20
```

Asynchronous thunks behave pretty similar, however we pass as parameter a function(*callback*) so whenever the value is ready (like the fetching of some data) it executes the function (resulting as a **sequentially and blocking** way of sorting asynchronous tasks).

Let’s code a program that fetches some data, but this time we will code it as intuitive as our brain would most likely sort it.

```jsx
function fetchAPI(rq, time) {
    const apiResponses = {
        'file1': 'First File',
        'file2': 'Second file'
    }

    setTimeout(function () {
        console.info(apiResponses[rq])
    }, time)
}

function executer(rq, time) {
        fetchAPI(rq, time) 
}

let th1 = executer('file1' , 3000)
let th2 = executer('file2' , 100)

// Second file
// First file
```

The output of the previous example is not what we initially expected, we want the *file1* to be fetched first and then the *file2.* The real problem here is with JS engine, because it is responsible for executing instructions as fast as possible without worrying about waiting for slow responses, so what happens here is that as the *file1* needs 3 seconds to execute and the *file2* just 100 seconds, the JS engine will choose the *file2* execution first than the *file1,* contrary to what we really want.

Now let’s consider the next example using **thunks** for managing async tasks correctly (sequentially and blocking) 

```jsx
function fetchAPI(rq, time, cb) {
    const apiResponses = {
        'file1': 'First File',
        'file2': 'Second file'
    }

    setTimeout(function () {
        cb(apiResponses[rq]) // - function ready() - lazy executed!
    }, time)
}

function executer(rq, time) {
    // we return a thunk with the - function ready() - as a 'future' callback
    return function thunk(cb) {
        fetchAPI(rq, time, cb) 
    }
}

// We return the function of  - function executer() - in the variable th, 
// as it is a function we can pass a param(in this case a callback - function ready() ), 
let th1 = executer('file1' , 3000)
let th2 = executer('file2' , 100)

th1(function ready(salida){
    console.info(salida) 
    // When JS engine comes in this line the first task has completed, 
    // so now we launch the second one
    th2(function ready(salida) {
        console.info(salida)
    })
})
```

**References** 

- [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
- [https://app.codesmith.io/blog/thoughts-on-javascript-thunks](https://app.codesmith.io/blog/thoughts-on-javascript-thunks)
- You Don’t Know JS Async & Performance