同期処理/非同期処理とは?
同期処理
コードが呼ばれたときに、処理が終わるまで、プロセスを止めること。
非同期処理
コードが呼ばれたときは、処理をする命令をするだけで、プロセスを止めない。
処理が終わったら「終わったよー」といって通知してくれるシステム。
UI系の言語はこっちが多い。JavaScript, Swift, Dart
サンプル
const fs = require('fs'); let id let i = 0; id = setInterval(()=>{ console.log(i++) },1) setTimeout(()=>{ if(false){ const data = fs.readFileSync(大きいファイル) clearInterval(id) }else{ fs.readFile(大きいファイル, (err, data) => { clearInterval(id) }); } }, 200)
これはJavaScriptのいいところ!
だけど、
1秒待って
Aと出力
1.2秒待って
Bと出力
1.6秒待って
Cと出力
1.1秒待って
Dと出力
1.2秒待って
Eと出力
1秒待って
Fと出力
1.6秒待って
Gと出力
これをプログラムで書くと
setTimeout(() => { console.log('A') setTimeout(() => { console.log('B') setTimeout(() => { console.log('C') setTimeout(() => { console.log('D') setTimeout(() => { console.log('E') setTimeout(() => { console.log('F') setTimeout(() => { console.log('G') }, 1600) }, 1000) }, 1200) }, 1100) }, 1600) }, 1200) }, 1000)
Promise
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } sleep(1000).then(()=>{ console.log('A') return sleep(1200) }).then(()=>{ console.log('B') return sleep(1600) }).then(()=>{ console.log('C') return sleep(1100) }).then(()=>{ console.log('D') return sleep(1200) }).then(()=>{ console.log('E') return sleep(1000) }).then(()=>{ console.log('F') return sleep(1600) }).then(()=>{ console.log('G') })
ちょっと良くなった
async/await
async/awaitはPromiseをもっとスッキリ書けるようにしてくれている構文
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function main(){ await sleep(1000) console.log('A') await sleep(1200) console.log('B') await sleep(1600) console.log('C') await sleep(1100) console.log('D') await sleep(1200) console.log('E') await sleep(1000) console.log('F') await sleep(1600) console.log('G') } main()
Promiseを返す関数はawaitで待つことができる。 ただしawaitはasyncの定義されている関数内でしか呼ぶことができない。
とにかく、async/awaitで書けないか?を常に調べる。Promiseを返すバージョンの関数がないかを調べる。できるだけasync/awaitを使う。