Concurrency

This commit is contained in:
Dumitru Deveatii 2019-01-29 17:25:00 +02:00
parent c6156ef887
commit 71dd4ba226

118
README.md
View file

@ -12,7 +12,7 @@ Inspired from [clean-code-javascript](https://github.com/ryanmcdermott/clean-cod
5. [Classes](#classes) *TODO*
6. [SOLID](#solid) *TODO*
7. [Testing](#testing) *TODO*
8. [Concurrency](#concurrency) *TODO*
8. [Concurrency](#concurrency)
9. [Error Handling](#error-handling) *TODO*
10. [Formatting](#formatting) *TODO*
11. [Comments](#comments)
@ -365,6 +365,122 @@ interface Config {
}
```
## Concurrency
### Prefer promises vs callbacks
Callbacks aren't clean, and they cause excessive amounts of nesting *(the callback hell)*.
There are utilities that transform existing functions using the callback style to a version that returns promises
(for Node.js see [`util.promisify`](https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original), for general purpose see [pify](https://www.npmjs.com/package/pify), [es6-promisify](https://www.npmjs.com/package/es6-promisify))
**Bad:**
```ts
import { get } from 'request';
import { writeFile } from 'fs';
function downloadPage(url: string, saveTo: string, callback: (error: Error, content?: string) => void){
get(url, (error, response) => {
if (error) {
callback(error);
} else {
writeFile(saveTo, response.body, (error) => {
if (error) {
callback(error);
} else {
callback(null, response.body);
}
});
}
})
}
downloadPage('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', 'article.html', (error, content) => {
if (error) {
console.error(error);
} else {
console.log(content);
}
});
```
Promises supports a few patterns that could be useful in some cases:
|Pattern|Description|
|-------|-----------|
|`Promise.resolve(value)`|Convert a value into a resolved promise.|
|`Promise.reject(error)`|Convert an error into a rejected promise.|
|`Promise.all(promises)`|Returns a new promise which is fulfilled with an array of fulfillment values for the passed promises or rejects with the reason of the first promise that rejects.|
|`Promise.race(promises)`|Returns a new promise which is fulfilled/rejected with the result/error of the first settled promise from the array of passed promises.|
`Promise.all` is especially useful when there is a need to run tasks in parallel. `Promise.race` makes it easier to implement things like timeouts for promises.
**Good:**
```ts
import { get } from 'request';
import { writeFile } from 'fs';
import { promisify } from 'util';
const write = promisify(writeFile);
function downloadPage(url: string, saveTo: string): Promise<string> {
return get(url)
.then(response => write(saveTo, response))
}
downloadPage('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', 'article.html')
.then(content => console.log(content))
.catch(error => console.error(error));
```
**[⬆ back to top](#table-of-contents)**
### Async/Await are even cleaner than Promises
With async/await syntax you can write code that is far cleaner and more understandable that chained promises. Within a function prefixed with `async` keyword you have a way to tell the JavaScript runtime to pause the execution of code on the `await` keyword (when used on a promise).
**Bad:**
```ts
import { get } from 'request';
import { writeFile } from 'fs';
import { promisify } from 'util';
const write = util.promisify(writeFile);
function downloadPage(url: string, saveTo: string): Promise<string> {
return get(url).then(response => write(saveTo, response))
}
downloadPage('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', 'article.html')
.then(content => console.log(content))
.catch(error => console.error(error));
```
**Good:**
```ts
import { get } from 'request';
import { writeFile } from 'fs';
import { promisify } from 'util';
const write = promisify(writeFile);
async function downloadPage(url: string, saveTo: string): Promise<string> {
const response = await get(url);
await write(saveTo, response);
return response;
}
// somewhere in an async function
try {
const content = await downloadPage('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', 'article.html');
console.log(content);
} catch (error) {
console.error(error);
}
```
## Comments
The use of a comments is an indication of failure to express without them. Code should be the only source of truth.