## Event-Based
* Javascript is single-threaded (like every sane GUI)
* no mutexes, no data-races
* browser main loop (hidden)
### Callbacks
```javascript
setTimeout(function onTimeout() { ... }, 10000);
setTimeout(() => { ... }, 10000); // ES6 arrow function
```
---
## Promises
```javascript
$http.get('/api/user').then(onSuccess).catch(onError);
function onSuccess(resp) {
var url = '/api/user/' + resp.data.id + '/info';
return $http.get(url).then(infoSuccess);
function infoSuccess(resp) {
console.log(resp.data.user_info);
}
}
function onError(reason) {
// show `reason` to user / redirect to login
}
```
#### ES6 Promises
Compatibility: any object with .then()
* Promise.resolve(value | promise) (replaces $q.when())
* Promise.reject(reason)
* Promise.all(iterable)
---
## Promise Hell
WebDriverJS using google:
```javascript
let driver = new Builder().forBrowser('firefox').build();
driver.get('http://www.google.com/ncr')
.then(_ => driver.findElement(By.name('q')))
.then(q => q.sendKeys('webdriver'))
.then(_ => driver.findElement(By.name('btnG')))
.then(btnG => btnG.click())
.then(_ => driver.wait(until.titleIs('webdriver - Google Search')
1000))
.then(_ => driver.quit(), e => {
console.error(e);
driver.quit();
});
```
* Source: https://github.com/SeleniumHQ/selenium/issues/2969
* You don't actually write this. (Promise Manager / Control Flow)
---
## async / await syntax
Protractor e2e test:
```javascript
it('should wait ...', async function() {
const usernameInput = element(...);
const name = element(...);
await browser.get('index.html#/form');
await expect(name.getText()).toEqual('Anon');
await usernameInput.clear();
await usernameInput.sendKeys('Jane');
await expect(name.getText()).toEqual('Jane');
});
```
### Advantages
Compared to old Control Flow:
* can actually set breakpoints
* better stack traces
* exception handling: try/catch (vs .catch(), onError)
---
## Puppeteer Example
```javascript
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
browser.close();
})();
```
### Parsing Cheat-Sheet
* async is a keyword, not a name
* arrow function
* immediately invoked (IFFE)
---
## ECMAScript
* ES5 (2009): "Internet Explorer"
* ES6 (2015): promises, arrow functions, generators (function*)
* ES7 (2016): -
* ES8 (2017): await/async
http://caniuse.com/#search=await (Node 7 and Node 8 (LTS))
## Libraries
* kriskowal/q (and Angular's $q) - Promises
* caolan/async, asyncawait, bluebird, etc. etc.
* babel can convert ES8 async function to FSM
---
## Callback Hell (Part II)
"Unlike Callback Hell, Promise Hell is self inflicted."
```javascript
fetchBook()
.then((book) => {
return formatBook(book)
.then((book) => {
return sendBookToPrinter(book);
});
});
```
Can rewrite as:
```javascript
fetchBook()
.then(formatBook)
.then(sendBookToPrinter);
```