Skip to content

Commit

Permalink
minor
Browse files Browse the repository at this point in the history
  • Loading branch information
iliakan committed Apr 5, 2019
1 parent d7d1c17 commit 2a39ef8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 21 deletions.
22 changes: 9 additions & 13 deletions 1-js/11-async/07-microtask-queue/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ That's why "code finished" in the example above shows first.

Promise handlers always go through that internal queue.

If there's a chain with multiple `.then/catch/finally`, then every one of them is executed asynchronously.
If there's a chain with multiple `.then/catch/finally`, then every one of them is executed asynchronously. That is, it first gets queued, and executed when the current code is complete and previously queued handlers are finished.

That is, it first gets queued, and executed when the current code is complete and previously queued handlers are finished.

What if the order matters for us? How to make `code finished` work after `promise done`?
**What if the order matters for us? How to make `code finished` work after `promise done`?**

Easy, just put it into the queue with `.then`:

Expand All @@ -56,7 +54,7 @@ Now the order is as intended.

## Event loop

Browser Javascript, as well as Node.js, is based on an *event loop*.
In-browser Javascript, as well as Node.js, is based on an *event loop*.

"Event loop" is a process when the engine sleeps and waits for events, then reacts on those and sleeps again.

Expand All @@ -73,7 +71,7 @@ Things happen -- the engine handles them -- and waits for more to happen (while

As you can see, there's also a queue here. A so-called "macrotask queue" (v8 term).

When an event happens, and the engine is busy, the event is enqueued.
When an event happens, while the engine is busy, its handling is enqueued.

For instance, while the engine is busy processing a network `fetch`, a user may move their mouse causing `mousemove`, and `setTimeout` may be due and so on, just as painted on the picture above.

Expand All @@ -90,7 +88,7 @@ In other words, the engine first executes all microtasks, and then takes a macro
For instance, take a look:

```js run
setTimeout(() => alert("timeout"), 0);
setTimeout(() => alert("timeout"));

Promise.resolve()
.then(() => alert("promise"));
Expand Down Expand Up @@ -122,9 +120,7 @@ Promise.resolve()

Naturally, `promise` shows up first, because `setTimeout` macrotask awaits in the less-priority macrotask queue.

**As a side effect, macrotasks are handled only when promises give the engine a "free time".**

So call have a promise chain that doesn't wait for anything, then things like `setTimeout` or event handlers can never get in the middle.
As a logical consequence, macrotasks are handled only when promises give the engine a "free time". So if we have a promise chain that doesn't wait for anything, then things like `setTimeout` or event handlers can never get in the middle.


## Unhandled rejection
Expand Down Expand Up @@ -159,12 +155,12 @@ promise.catch(err => alert('caught'));
window.addEventListener('unhandledrejection', event => alert(event.reason));
```

Now let's say, we'll be catching the error, but after an extremely small delay:
Now let's say, we'll be catching the error, but after `setTimeout`:

```js run
let promise = Promise.reject(new Error("Promise Failed!"));
*!*
setTimeout(() => promise.catch(err => alert('caught')), 0);
setTimeout(() => promise.catch(err => alert('caught')));
*/!*

// Error: Promise Failed!
Expand All @@ -173,7 +169,7 @@ window.addEventListener('unhandledrejection', event => alert(event.reason));

Now the unhandled rejction appears again. Why? Because `unhandledrejection` triggers when the microtask queue is complete. The engine examines promises and, if any of them is in "rejected" state, then the event is generated.

In the example above `setTimeout` adds the `.catch`, and it triggers too, of course it does, but later, after the event has already occured.
In the example, the `.catch` added by `setTimeout` triggers too, of course it does, but later, after `unhandledrejection` has already occured.

## Summary

Expand Down
25 changes: 17 additions & 8 deletions 1-js/11-async/08-async-await/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,30 @@ let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
```
So we need to have a wrapping async function for the code that awaits. Just as in the example above.
We can wrap it into an anonymous async function, like this:
```js run
(async () => {
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
...
})();
```
````
````smart header="`await` accepts thenables"
Like `promise.then`, `await` allows to use thenable objects (those with a callable `then` method). Again, the idea is that a 3rd-party object may not be a promise, but promise-compatible: if it supports `.then`, that's enough to use with `await`.
````smart header="`await` accepts \"thenables\""
Like `promise.then`, `await` allows to use thenable objects (those with a callable `then` method). The idea is that a 3rd-party object may not be a promise, but promise-compatible: if it supports `.then`, that's enough to use with `await`.

Here's a demo `Thenable` class, the `await` below accepts its instances:

For instance, here `await` accepts `new Thenable(1)`:
```js run
class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
alert(resolve); // function() { native code }
alert(resolve);
// resolve with this.num*2 after 1000ms
setTimeout(() => resolve(this.num * 2), 1000); // (*)
}
Expand All @@ -161,9 +172,7 @@ If `await` gets a non-promise object with `.then`, it calls that method providin
````
````smart header="Async methods"
A class method can also be async, just put `async` before it.
Like here:
To declare an async class method, just prepend it with `async`:
```js run
class Waiter {
Expand Down

0 comments on commit 2a39ef8

Please sign in to comment.