Deferring to the User Interface
Tags: javascript, webdev
Published: 2021-11-25 10:13:37

When executing long-running JavaScript code the web browser's User Interface (UI) remains unresponsive thanks to the infamous single-threaded nature of JavaScript. Consequently it's useful in time-consuming JavaScript code, to defer back to the UI from time to time, to let user events like scrolling, clicking and typing all take their natural course.

That proves to be quite a tricky thing. Or not, depending on how you look at it. 

[Mario Figueiredo](https://stackoverflow.com/users/7385781/mario-figueiredo) provides a [solution](https://stackoverflow.com/a/60149544/4002633) on [Stack Overflow](https://stackoverflow.com/) and I recast it here, essentially as follows:

```javascript
function defer_to_UI(how_long = 0) {
     return new Promise(resolve => setTimeout(resolve, how_long));
}
```

You have to love JavaScript no? Such abundant clarity not? (and I've taken liberties to clarify Mario's code a little too).

# So what is actually going on here? 

`setTimeout`, as it happens, schedules something to happen in the future by a specified number of milliseconds (`how_long`) and if that is 0ms it schedules it to happen ASAP in the future. What does that mean?  

Recalling that JavaScript is essentially single-threaded, what this does is put the call to `resolve()` on a queue. The same queue as it happens that UI events are sitting in, waiting to be handled. 

In the context of the long running style in-lining code I'm running, they are not being handled as the styles are being in-lined. Because the in-lining function is running, they are waiting patiently in the queue until it's done. Which as you may recall [could be 30 seconds](https://dev.to/thumbone/html-style-in-lining-performance-and-what-to-about-it-4a55).

`setTimeout()` is a function that asks the browser to run a timer (for `how_long` microseconds), and when the timer is up, to place a call to the function (`resolve()` in this case) on the event loop queue. But the function `resolve` is a mystery here. It is provided as the argument to a function that is wrapped in a promise. Wowsers, what? 
![What?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5a3slf389g0bqxpjze7e.jpg)

# Promises, promises

A promise is just a JavaScript object that maintains a state of either "pending", "fulfilled" or "rejected", with a few convenient callback hooks to set that state.
![Promise](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mn129ygaj4qnvg3gp2m.jpeg)

When a Promise is instantiated it's state is initially "pending" and its constructor takes one argument, which must be a function. That  function is immediately executed, and given two arguments, also functions, the first of which must be called to set the state of the promise to "fulfilled" and the second of which must be called to set the state of the promise to "rejected". In a sense the argument to the constructor of a promise is the promised function - it is run, and to let the world know it succeeded it is asked to call the function it received as first argument, and to let the world know it failed it is asked to call the function provided as its second argument, and if it calls neither well ... we'll get to that (but no prize if you guess: the promise simply remains "pending").
![Pending](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rin8mcbi2dcojk4nkrmu.jpg)

To illustrate, a few examples are helpful.

A promise that is immediately fulfilled (which isn't wildly useful) is created with:

`new Promise(resolve => resolve());`

That is the function just calls the first argument to flag the promise as "fulfilled". Note that this also uses JavaScript's [arrow notation for functions](https://www.w3schools.com/Js/js_arrow_function.asp). It can also be written any number of different ways using other notations (JavaScript is oh so flexible in that space it seems). Here are a few:

`new Promise(function(x) {x()});` - note the name of the first argument is irrelevant. It's the promised function's argument, and can be called whatever you like. All that is important is that the promised function knows this argument is itself a function that it must call to tell the world that it has delivered on the promise - that it is done. 

```javascript
function deliver_me_my_promise(set_state_to_fulfilled) {
	set_state_to_fulfilled();
}
new Promise(deliver_me_my_promised);
```

Which is (literally) more colourful, as now we give the promised function a name, it's no longer anonymous, we've called it, oh so descriptively `deliver_me_my_promise()` and its first argument has a revealing name too: `set_state_to_fulfilled`. All it does is call `set_state_to_fulfilled()` and that indeed is all that happens, the Promise object now has a state of "fulfilled"

Of course, an immediately fulfilling promise isn't so useful. Nothing much happens.

## But, wait ...

Enter `await` - which is going to make it useful as we will shortly see.
![Waiting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmh4i5hb1krfodth1g17.jpg)

`await` is an operator, that waits on a Promise to fulfill (or reject, but let's ignore that for now). And so:

`await new Promise(resolve => resolve());`

will do nothing, just return. The promise thus created, we just noticed, is fulfilled when it's created and `await` checks to see if it's fulfilled and if so, returns. Which it does. This is in fact one of JavaScript's more interesting null statements, the equivalent of a [Python `pass`](https://www.w3schools.com/python/ref_keyword_pass.asp).

But what if the promise is pending? That is, it has not yet called either its first or second argument. 

In that case `await`, true to its name, does not return. It waits patiently (we'll get to how later).

To illustrate though. we could write a promise that is perpetually pending easily enough, by not calling the provided resolver. Here's another useless promise, one that is never fulfilled and always pending:

`new Promise(resolve = {})` - as it happens, `{}` is the more common form of a JavaScript "do nothing" statement. Hang on, just for a laugh, you probably realised we could write this cute, always pending, promise using the fancier "do nothing" statement we just saw:

`new Promise(resolve = await new Promise(resolve = resolve()))`

Pointless, and for good humour alone of course to define one promise in terms of another that does nothing.

We could again write this in different ways like:

```javascript
function deliver_me_my_promise(set_state_to_fulfilled) { }
new Promise(deliver_me_my_promise);
```

Essentially the promise executor (`deliver_me_my_promise()` in this case), the function it runs when it's created, never calls the provided resolver, never tells the Promise that it is "fulfilled" and so it sits there in a perpetual "pending" state. 

Now if we `await` that:

`await new Promise(resolve => {});`

await never returns. Just waits forever. This never-fulfilled promise is of course as useless as the immediately-fulfilled promise was. But helps to illustrate what `await` does. 

As an aside, the means by which it waits is another topic for another day perhaps, but is often described as syntactic sugar around a yield/next structure, which means, in a nutshell only, that:

* the function that calls `await` has its state saved (probably on the heap - where most stuff is stored), 
* registers this fact with the promise (where it's remembered), returns (to the function calling it) and 
* when it is next called it will continue at the line after the `await`. 

It is next called as it happens, when the promised function calls either of the functions it received as arguments, the first to fulfill and the second to reject. 

These functions are provided by the promise and what they do when called, is set the state of the promise accordingly and call the function that is `await`ing (remember that it registered its wait with the promise, and its state was saved so that on next call it continues on the line after the `await`). This is the callback hook we referred to earlier, that is when the promised function calls either of its first two arguments, that sets the state of the promise to fulfilled or rejected respectively **and** calls back any functions that registered themselves with the promise as "waiting".

## More useful promises

Your browser (through what's called its Web API) of course provides more useful promises (than our immediately and never fulfilled promises). [`fetch`](https://javascript.info/fetch) is such a useful built-in promise. It fetches a URL, which can take some time, so returns a promise. If you're happy to wait for the URL to return data then `await fetch(URL)` is fine and `await` will pause until it is no longer pending but fulfilled (or rejected). Of course if you don't want to wait for URL you can attach a callback to the promise using it's `.then()` method as in: 

`fetch(URL).then(call_this_function)`. 

That simply registers `call_this_function` with the promise, to be called when the promised function calls its first argument. Very much like `await` registers the function it's in that way.

Which means that `call_this_function` won't be called until JavaScript is idle (aka the stack is empty or all your JavaScript functions have finished). Only then does the event loop look at this queue and call the  next thing in it (pulling it off the queue).

## The most useful promise (to us here)

We have come full loop, back to `setTimeout()`. This is a native JavaScript function places a(nother) function call on the end of the event loop's queue and so this:

`await new Promise(first_argument => setTimeout(first_argument, 0));`

creates a Promise that runs `setTimeout(first_argument, 0)` which places a call to `first_argument()` on the end of the event loop's queue. 

`first_argument()` sets the state of the promise to "fulfilled" and calls any functions that registered themselves with the promise earlier. 

`await` does just that, registers itself with the Promise requesting a call back to the same line and it registers that interest, perforce, before `first_argument()` is called, because the call to `first_argument()` is at the end of the event queue which JavaScript only starts processing now that we have given up control with `await`.

So while JavaScript is running, `await` registered it's desire to be called back when `first_argument()` is called, and `first_argument()` is called after all JavaScript has finished running, and all events queued ahead of the `first_argument()` call on the event loop have been called (and completed). 

On the event loop, it's first-in best-dressed, and any UI events that were queued while JavaScript was running are dealt with (browser updates the rendered DOM) and then when they are done, the call to `first_argument()` (that `setTimeout()` put there) eventually runs and we carry on where we left off and the UI events have been dealt with. 

Of course we tend to name that first argument `resolve` to produce: `await new Promise(resolve => setTimeout(resolve, 0));`. It doesn't matter what it's called, the promise just provides a call back function as the first argument and the name is a conventional mnemonic to remind us this is the function to call, to let the promise know it is fulfilled and to call any registered callbacks.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wx0lo40mnzv3nt6y36by.png)

To recap:

- When the `Promise` is instantiated it runs the function provided as its only argument - the nameless function `function noname(resolve) { setTimeout(resolve, 0) }` immediately.
- `setTimeout` then puts a call to `resolve()` on the end of a event loop queue, behind any waiting UI events. 
- `await` pauses until `resolve` is called, which does not happen until after all the UI events that were queued before it are called (and handled)

## More on pausing

But what does "pausing" mean here? This is a curio worth understanding too, because the event loop queue is not processed until JavaScript is done. So how does it come to be done if it's paused?

The trick is that `await` returns, it doesn't pause at all, that is a misnomer. It does save the state of the function it's in first and registers a callback to that state with a promise, but after that it returns. That is the `await` statement is a fancy variant of the `return` statement. When you execute `await` you are practically executing a dressed variant of `return`.

The JavaScript continues executing in the function that called the one that the `await` was in.

To make clear what is happening here, a firm rule exists in JavaScript, that a function that uses `await` must be marked `async`. In a nutshell this is illegal:

```javascript
function myfunc() {
    await new Promise(resolve => setTimeout(resolve, 0));
    return "I'm done";
}
```

we are obliged to write it so:

```javascript
async function myfunc() {
    await new Promise(resolve => setTimeout(resolve, 0));
    return "I'm done";
}
```

In no small part, this is intended to remind anyone who calls this function that it may not be finished when it returns ... 

Forsooth, guess what?  `function myfunc()` returns a string (or it would if it were legal and we took the `await` out), but `async function myfunc()` returns a promise for the string and that promise is still "pending" if `await` is called, only when `myfunc()` returns "I'm done" is the promise marked "fulfilled" (and and registered call backs are called).

And so if you're content with a promise you can call `myfunc()` and it will return a promise. But if you need a string, you can call `await myfunc()` and you can see in this manner that `await` begets `await` and `async` is a bit catchy, like a cold ... once a function uses `await` and hence must be `async`, slowly most functions that rely on it become `async` as well, if they need results, otherwise a chain of promises is returned which is is fine too, if all you need is a promise. He who `awaits` gets the results of the promise!

But we were wondering how `await` pauses. And it should be clear that it doesn't nor does it have to, JavaScript will still run to completion even though it is seemingly paused. 

It is not paused, it has saved its state, registered a callback with a Promise (just an object on the heap), which the browser has access to as well. But in so doing it returns to its calling function. That function can either:

- also `await` this function, in which case the same applies (recursively up all the calling functions until eventually JavaScript runs to completion, the awaits all having returned).
- not `await`, be a normal function, which just runs to completion. 

## Then again ...

Rather than `await` it is often useful to register explicit callbacks with `.then()`.

In the above example we could `await myfunc()` or `myfunc().then(call_this_function)`. Both register a call back with the promise. The `await` registers a call back to the same function (state preserved). The `.then()` registers a call back to `call_this_function` (any function we name). 

Either way, both return and JavaScript runs to completion. it is when a browser event calls `resolve()` (the first argument supplied to the promised function) that the promise's state is updated to "fulfilled" and the promise honours the call back requests registered with it (either back to the `await` statement or the function registered with `.then()`)

And `setTimeout()` is the means by which we place a call to `resolve()` on the browser's to-do list! 

# Wrapping up

But back to our cause which is deferring to the UI. We have a solution and we know how it works now.

```javascript
function defer_to_UI(how_long = 0) {
     return new Promise(resolve => setTimeout(resolve, how_long));
}
```

And in our time-consuming (UI locking) style in-lining function, from time to time we can `await defer_to_UI()`. 

The function of the `await` being only to save the state of our function, register a desire to be called back to this same line, and return. So when we are called back we continue on the next line like nothing happened ... except of course that we released control (returned) and offered JavaScript the chance to process tasks on the event queue (the UI responds).

From time to time, but ...

# How often?

If we look at my most extreme example of about 100,000 elements with styles to in-line taking about 30 seconds to do, if we defer to the UI after each element is processed it takes about 11 minutes to complete! Wow! And that is with no UI interactions. That, apparently, is the mere overhead of re-queuing ourselves 100,000 times. 

So clearly we don't want to do that. Instead we'd `defer_to_UI` at some lower frequency, but what frequency? Either way, to get a feel for things, we should add a progress bar to the style in-lining function.

Which we will look at in the next article ...