Skip to content

Commit

Permalink
Added guide on async calls
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimirkosmala committed Jan 30, 2018
1 parent d63f9d0 commit f03cbeb
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Create mini applications step by step with explanations.

### Guides

- [Async calls with fetch (ajax) and websocket](./docs/guides/fetch-websocket.md)
- [Async calls (ajax)](./docs/guides/fetch-websocket.md)
- [Scale the code of your application (architecture)](./docs/guides/scale-app.md)
- [From imperative to reactive programming (jQuery to React)](./docs/guides/reactive-programming.md)

Expand Down
109 changes: 109 additions & 0 deletions docs/guides/async-calls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Guide - Async calls (ajax)

Javascript deals well with asynchronous calls like network requests. Historically it was implemented though callback functions like this.

```js
request(arguments, function callback(error, result) {
// do something with result
});
```

But this leads to spaghetti code and a more formal way was created: Promises.

```js
var resultPromise = request(arguments);
resultPromise.then(function callback(result) {

});
resultPromise.catch(function callback(error) {

});
```

Notice that the callbacks are now binded to an object, the promise.

Then Javascript went full asynchronous is the langage itself with await.

```js
try {
var resultPromise = await request(arguments);
} catch (error) {

}
```

We can integrate promises with an observable model:

```js
class Model extends Observable {
fetchImages() {
return fetch('/api/images')
.then((images) => this.setImages(images))
.catch((error) => this.handleErrors(error));
}

setImages(images) {
this.images = images;
this.notify();
}

handleErrors(error) {
this.error = error;
this.notify();
}
}
```

The method fetchImages will create a network request and return a promise. When the promise is finished it will either call the success method or a generic handler.

Because you often have a lot of requests, it is a efficient to have a generic handler for errors which will for example print an error message to the user.

fetchImages also returns a promise, the caller could use it to know that the call is finished or not and avoid calling again while the request is still in progress.

Of course we call `notify()` each time the model changes, for both `then` and `catch` callbacks.

Here is a practical example where we don't want the user to request again when a request has been made:

```js
class Model extends Observable {
fetchImages() {
if (this.fetchingImages) {
return;
}

this.fetchingImages = true;
this.notify();

return fetch('/api/images')
.then((images) => {
this.setImages(images);
})
.catch((error) => {
this.handleErrors(error);
})
.finally((error) => {
this.fetchingImages = false;
this.notify();
});
}

setImages(images) {
this.images = images;
this.notify();
}

handleErrors(error) {
this.error = error;
this.notify();
}
}

function button(model) {
const action = model.fetchingImages ? e => model.fetchImages() : null;
const className = model.fetchingImages ? 'disabled' : '';
return h('button', {onclick: action, class: className}, 'Fetch images')
}
```

We used the method `finally` of the promise to clean up the request.

2 changes: 0 additions & 2 deletions docs/guides/fetch-websocket.md

This file was deleted.

0 comments on commit f03cbeb

Please sign in to comment.