-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
36 changed files
with
2,244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,372 @@ | ||
--- | ||
title: Fyrirlestur – Ósamstillt forritun | ||
--- | ||
|
||
# Fyrirlestur – Ósamstillt forritun | ||
|
||
## Vefforritun 1 — TÖL107G | ||
|
||
### Ólafur Sverrir Kjartansson, [osk@hi.is](mailto:osk@hi.is) | ||
|
||
--- | ||
|
||
## Ósamstillt forritun (async programming) | ||
|
||
* Þegar forritin okkar fara að nýta hluti sem eru ekki í minni þurfum við að beita öðrum aðferðum í forritun | ||
* Það er _hratt_ að sækja hluti í minni, _hægara_ að sækja á disk og (oftast) enn _hægara_ að sækja yfir net | ||
* Bíðum ekki eftir því að beiðni klárist, nýtum _ósamstillta forritun_ (asynchronous/async programming) | ||
|
||
*** | ||
|
||
## Samstillt forritun | ||
|
||
* Flest forrit sem þið hafið séð hingað til eru samstillt—þau keyra eina línu í einu, eitt fall í einu—eru línuleg | ||
* Hægt að nota _þræði_, JavaScript hefur **ekki** stuðning við þá | ||
* Notum async forritun með _event loop_ á einum þræði | ||
* Höldum CPU ekki uppteknum á meðan beðið | ||
|
||
*** | ||
|
||
![Dæmi um mismunandi forritun](img/control-io.svg "Mynd frá https://eloquentjavascript.net/11_async.html") | ||
|
||
*** | ||
|
||
## Callbacks | ||
|
||
* Ein leið til að vinna með async kóða, t.d. í atburðum | ||
* Köllum í fall sem tekur langan tíma, eða verður kallað í seinna, með _callback_ argument | ||
* Fallið kallar í _callback_ fall með niðurstöðu þegar búið | ||
* Ef við köllum í annað fall sem tekur langan tíma úr _callback_ þurfum við annað callback o.s.fr. o.s.fr. | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-alert --> | ||
|
||
```javascript | ||
// snoozea í 5s, síðan 3s og að lokum 1s | ||
setTimeout(() => { | ||
alert('Vakna!'); | ||
setTimeout(() => { | ||
alert('Vakna núna!'); | ||
setTimeout(() => { | ||
alert('VAKNA!!'); | ||
}, 1000); | ||
}, 3000); | ||
}, 5000); | ||
``` | ||
|
||
*** | ||
|
||
* Getum búið til almennt fall `snooze` sem birtir skilaboð eftir ákveðinn tíma | ||
* Getur aukalega tekið við _callback_ falli sem keyrir í framhaldinu | ||
* Verður aðeins læsilegra | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-alert --> | ||
|
||
```javascript | ||
function snooze(s, msg, callback) { | ||
setTimeout(() => { | ||
alert(msg); | ||
if (callback) { | ||
callback(); | ||
} | ||
}, 1000 * s); | ||
} | ||
|
||
snooze(5, 'Vakna', () => { | ||
snooze(3, 'Vakna núna!', () => { | ||
snooze(1, 'VAKNA!!'); | ||
}); | ||
}); | ||
``` | ||
|
||
*** | ||
|
||
* [snooze dæmi](daemi/01.snooze.js) | ||
|
||
--- | ||
|
||
## Promises | ||
|
||
* [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) er hjúpun fyrir gildi sem _mun verða til_ í framtíðinni | ||
* Gerir asynchronous forritun auðveldari | ||
* Öðruvísi hugtak en callbacks, vinnum með hjúpuð gildi í staðinn fyrir eitthvað sem við köllum í framhaldi | ||
|
||
*** | ||
|
||
* Þegar við skilgreinum Promise köllum við í: | ||
* `resolve` með gildi þegar við höfum lokið aðgerð | ||
* `reject` með villu ef eitthvað fer úrskeiðis | ||
|
||
*** | ||
|
||
* Þegar við vinnum með promise skilgreinum við | ||
* `then` callback til að vinna með gildið, fær skilagildi sem argument | ||
* `catch` callback til að vinna með villu, fær villu sem argument | ||
* `then` og `catch` eru föll á Promise | ||
|
||
*** | ||
|
||
* Getum sent promise gildi á milli og bætt við `then` og `catch`! | ||
* Ef búið er að uppfylla en við köllum í seinna, þá fáum við svarið | ||
|
||
*** | ||
|
||
```javascript | ||
const fifteen = Promise.resolve(15); | ||
fifteen | ||
.then(v => console.log(`Got ${v}`)); | ||
// → Got 15 | ||
setTimeout(() => { | ||
fifteen | ||
.then((value) => { | ||
console.log('Sama svar, sekúndu seinna', value) | ||
}); | ||
}, 1000); | ||
``` | ||
|
||
*** | ||
|
||
* [promise dæmi](daemi/02.promise.js) | ||
|
||
--- | ||
|
||
## Villur | ||
|
||
* Villumeðhöndlun með callbacks verður hratt mjög ólæsileg og flókin | ||
* Eitt argument fyrir hvað gerist ef við fáum gildi, annað fyrir villu | ||
* Blöndum saman villumeðhöndlun og lógík | ||
* Mjög mikið inndreginn kóði, _callback hell_ | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef --> | ||
|
||
```javascript | ||
snooze(5, 'Vakna', () => { | ||
if (ok) { | ||
snooze(3, 'Vakna núna!', () => { | ||
if (okok) { | ||
snooze(1, 'VAKNA!!'); | ||
} else { | ||
// villa | ||
} | ||
}); | ||
} else { | ||
// villa | ||
} | ||
}); | ||
``` | ||
|
||
*** | ||
|
||
* `catch` eftir `then` í Promise sér um villur í öllum kóða sem á undan kemur | ||
* Þurfum ekki að hafa villumeðhöndlun innan kóða sem sér um að bregðast við gildi | ||
|
||
*** | ||
|
||
<!-- eslint-disable implicit-arrow-linebreak --> | ||
|
||
```javascript | ||
function futureMessage(msg) { | ||
return new Promise((resolve, reject) => { | ||
if (msg === 'foo') { | ||
reject(new Error('No foo!')); | ||
} | ||
|
||
setTimeout(() => | ||
resolve(`${msg} from future`), 2000); | ||
}); | ||
} | ||
|
||
futureMessage('Hi!') | ||
.then(msg => console.log(msg)); | ||
// "Hi! from future!" eftir 2 sek | ||
``` | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef --> | ||
|
||
```javascript | ||
futureMessage('foo') | ||
.then(msg => console.log(msg)) | ||
.catch(e => console.log(e)); | ||
// "No foo!" strax | ||
``` | ||
|
||
*** | ||
|
||
## Stöður á promise | ||
|
||
Promise getur verið í einni af þrem stöðum: | ||
|
||
* `pending`, verið að bíða eftir gildi | ||
* `fulfilled`, búið að uppfylla loforð með gildi | ||
* `rejected`, búið að hafna loforði með villu | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef --> | ||
|
||
```javascript | ||
const p = futureMessage('hmm'); | ||
function foo(promise) { | ||
console.log(promise); | ||
|
||
promise.then(msg => console.log(msg)); | ||
|
||
return 'Handling promise...'; | ||
} | ||
foo(p); | ||
// Promise { ... } | ||
// "Handling promise..." | ||
// "hmm from the future!" eftir 2 sek | ||
``` | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-alert --> | ||
|
||
```javascript | ||
function snooze(s, msg) { | ||
return new Promise((resolve) => { | ||
setTimeout(() => { | ||
resolve(msg); | ||
}, s * 1000); | ||
}); | ||
} | ||
|
||
snooze(5, 'Vakna') | ||
.then(msg => alert(msg)) | ||
.then(() => snooze(3, 'Vakna núna!')) | ||
.then(msg => alert(msg)) | ||
.then(() => snooze(1, 'VAKNA!!!')) | ||
.then(msg => alert(msg)); | ||
``` | ||
|
||
*** | ||
|
||
* [promise og villumeðhöndlun dæmi](daemi/03.future-message.js) | ||
* [snooze dæmi með promises](daemi/04.snooze-promise.js) | ||
|
||
--- | ||
|
||
## Promise.all | ||
|
||
* `Promise.all` tekur við fylki af Promise og skilar Promise | ||
* Ef eitthvert rejactarar er Promise rejectað | ||
* Niðurstaða er fylki með niðurstöðu í réttri röð m.v. uppruna | ||
|
||
*** | ||
|
||
## Promise.race | ||
|
||
* `Promise.race` tekur við fylki af Promise og skilar Promise | ||
* Skilar niðurstöðu úr fyrsta Promise sem lýkur eða rejectar | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef --> | ||
|
||
```javascript | ||
const snoozefest = Promise.all([ | ||
snooze(5, 'Vakna'), | ||
snooze(3, 'Vakna núna!'), | ||
snooze(1, 'VAKNA!!!'), | ||
]) | ||
.then(result => console.log(result)); | ||
|
||
console.log(snoozefest); | ||
// Promise {pending} | ||
// 5s seinna.. | ||
// ["Vakna", "Vakna núna!", "VAKNA!!!"] | ||
``` | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef --> | ||
|
||
```javascript | ||
// snooze eins og áður | ||
|
||
Promise.race([ | ||
snooze(5, 'Vakna'), | ||
snooze(3, 'Vakna núna!'), | ||
snooze(1, 'VAKNA!!!'), | ||
]) | ||
.then(result => console.log(result)); | ||
|
||
// 1s seinna.. | ||
// "VAKNA!!!" | ||
``` | ||
|
||
*** | ||
|
||
* [all og race dæmi](daemi/05.all-race.js) | ||
|
||
--- | ||
|
||
## async og await | ||
|
||
* [`async await`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await) er önnur leið til að vinna með async kóða | ||
* Leyfir okkur að _bíða_ eftir async aðgerð í línulegu flæði | ||
* Merkjum föll sem þarf að bíða eftir með `async` | ||
* Merkjum að við ætlum að bíða með `await` | ||
* Grípum villur með `try catch` | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef, no-alert --> | ||
|
||
```javascript | ||
// snooze fall eins og áður | ||
async function snoozer() { | ||
alert(await snooze(5, 'Vakna')); | ||
alert(await snooze(3, 'Vakna núna')); | ||
alert(await snooze(1, 'VAKNA!!!')); | ||
} | ||
|
||
snoozer(); | ||
``` | ||
|
||
*** | ||
|
||
<!-- eslint-disable no-undef --> | ||
|
||
```javascript | ||
// futureMessage eins og áður | ||
async function future() { | ||
try { | ||
const res = await futureMessage('foo'); | ||
console.log(res); | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
} | ||
|
||
future(); | ||
``` | ||
|
||
*** | ||
|
||
* Getum ekki notað `await` í global scope—verður að vera innan `async` falls | ||
* `async` fallið skilar Promise! | ||
* `async await` er _syntactic sugar_ fyrir Promise | ||
* Ættum að hafa `catch` á það fall til að vera örugg um að missa ekki af villum | ||
|
||
*** | ||
|
||
## async forritun | ||
|
||
* Async forritun er erfið til að byrja með | ||
* Lærum ekki á einum degi eða einni viku en margt af því sem við gerum á vefnum **er** async | ||
* Sjáum dæmi í atburðum og _ajax_ beiðnum | ||
* Förum enn dýpra í vefforritun 2 | ||
|
||
*** | ||
|
||
* [async await dæmi](daemi/06.futureMessage-async.js) | ||
* [snooze dæmi með async await](daemi/07.snooze-async.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
rules: { | ||
// leyfum alert() | ||
'no-alert': 0, | ||
}, | ||
}; |
Oops, something went wrong.