Share
Embed
Callback to Promise and beyond
Daiki Kuriyama
February 01, 2019
Transcript
28 slides
-
/PEFKTʹ͓͚Δඇಉظॲཧͱϑϩʔ੍ޚͷྺ࢙ "TZODUZQF /PEFWFSTJPO $BMMCBDL 3FNPWFQSPNJTFT W BTZOD
OQN CMVFCJSE OQN 2 OQN 1SPNJTF" W 7 (FOFSBUPS W 7 "TZOD'VODUJPOT BTZODBXBJU W 7 "TZOD*UFSBUJPO GPSBXBJUPG &YQFSJNFOUBM -
$BMMCBDLͱ1SPNJTFͷΠϯλʔϑΣʔεΛཱ྆ͤ͞Δ $BMMCBDLΛলུͨ࣌͠ʹ1SPNJTFΛฦ͢ 1SPNJTFઐ༻ͷΠϯλʔϑΣʔεΛՃ͢Δ ‣ 1SPNJTFܕͷϞδϡʔϧΛฦ͢ ‣
ϝιουνΣʔϯ͔Β1SPNJTFΛฦ͢ ‣ 4VGpY͖ͷ͔ؔΒ1SPNJTFΛฦ͢ ϞδϡʔϧͰ$BMMCBDLͱ1SPNJTFͷΠϯλʔϑΣʔεΛཱ྆ͤ͞Δํ๏ʹ͍ͭ͘ ͔ͷબࢶ͕͋ΓɺͦΕͧΕʹϝϦοτͱσϝϦοτ͕ଘࡏ͢Δɻ -
$BMMCBDLͱ1SPNJTFͷཱ྆ $BMMCBDLΛলུͨ࣌͠ʹ1SPNJTF͕ฦΔ // Callback func((data) => { console.log(data) }) //
Promise const data = await func() console.log(data) ϚʔέοτΛௐࠪ͢ΔݶΓ͜ͷελΠϧͷ࠾༻ྫଟ͘ɺ+BWB4DSJQUͷจԽΛݟͯ ύϥϝʔλΛলུͯ͠ڍಈ͕มΘΔΈଟ͘ଘࡏ͍ͯ͠Δɻ ϝιου͝ͱͷஈ֊తͳ1SPNJTFԽ͕ՄೳͰɺকདྷతͳ$BMMCBDLͷഇࢭࢹʹೖ Ε͍͢ɻͨͩ͠TFU5JNFPVUDIJME@QSPDFTTFYFDͷΑ͏ͳίʔϧόοΫؔ Λड͚औΓɺಉ࣌ʹฦΓଘࡏ͢Δؔͱ૬ੑ͕ѱ͍ͨΊҙ͕ඞཁɻ -
$BMMCBDLͱ1SPNJTFͷཱ྆ 1SPNJTFܕͷϞδϡʔϧΛฦ͢ // Callback const fs = require('fs') fs.readFile('/etc/hosts', (err,
data) => { console.log(data) }) // Promise const fs = require('fs').promises const data = await fs.readFile('/etc/hosts') console.log(data) /PEFKTͷຊମ͕࠾༻͍ͯ͠Δํ๏ɻͯ͢ͷϝιουΛҰׅͰ1SPNJTFԽͰ͖Δͱ ͍͏ར͕͋Γɺ·ͨϞδϡʔϧͷ։ൃऀࢹͰطଘͷ$BMMCBDLؔʹखΛՃ͑Δ ඞཁ͕ͳ͍ͱ͍͏ར͋Δɻ ͔͠͠Ϟδϡʔϧʹଘࡏ͢Δͯ͢ͷཁૉΛෳͯ͠վम͢Δඞཁ͕͋ΔͨΊɺରԠ ͷίετվम࣌ʹूத͢Δɻ -
$BMMCBDLͱ1SPNJTFͷཱ྆ ϝιουνΣʔϯ͔Β1SPNJTFΛฦ͢ // Callback func((data) => { console.log(data) }) //
Promise const data = await func().promise() console.log(data) "844%,GPS+BWB4DSJQUͳͲ͕࠾༻͍ͯ͠Δํ๏ɻ1SPNJTFʹݶΒͣɺ4USFBN ͷΑ͏ͳෳύλʔϯͷΠϯλʔϑΣʔεΛ໌ࣔతʹࢦఆͯ͠ฦ͢͜ͱͰ͖Δɻ طଘͷ$BMMCBDLؔʹखΛՃ͑Δඞཁ͕ͳ͍ͱ͍͏ར͕͋ΓɺϞδϡʔϧͷϝιο υΛ෦తʹ1SPNJTFରԠ͍ͯ͘͜͠ͱͰ͖Δ͕ɺকདྷతͳ$BMMCBDLͷഇࢭΛࢹ ʹೖΕΔ߹ѻ͍͕͍͠ɻ -
$BMMCBDLͱ1SPNJTFͷཱ྆ 4VGpY͖ͷ͔ؔΒ1SPNJTFΛฦ͢ // Callback func((data) => { console.log(data) }) //
Promise const data = await funcAsync() console.log(data) VUJMQSPNJTJGZCMVFCJSEQSPNJTJGZ"MMͳͲΛར༻͢Δ͜ͱʹΑͬͯɺ࠷খݶ ͷίετͰϞδϡʔϧͷϝιουΛ1SPNJTFʹରԠ͢Δ͜ͱ͕Ͱ͖Δɻ কདྷతͳ$BMMCBDLͷഇࢭΛߟ͑Δ߹ɺޓੑʹͲ͏ରॲ͢Δ͔͕·͍͠ɻ4VGpYΛ ҡ࣋͢Δ͔ɺ·ͨ4VGpYΛআڈͯ͠1SPNJTFͷར༻ऀʹෛՙΛ༩͑Δ͔ͷબ͕ඞཁɻ -
֤ύλʔϯͷ۩ମతͳ࣮ํ๏ϒϩάͷهࣄʹɻ͓͢͢Ίஈ֊తͳ1SPNJTFԽͱ $BMMCBDLͷഇࢭΛࢹʹೖΕ͍͢ʮ$BMMCBDLΛলུͨ࣌͠ʹ1SPNJTFΛฦ͢ʯํ๏ɻ $BMMCBDLͱ1SPNJTFͷΠϯλʔϑΣʔεΛཱ྆ͤ͞Δ $BMMCBDLΛলུͨ࣌͠ʹ1SPNJTFΛฦ͢ 1SPNJTFઐ༻ͷΠϯλʔϑΣʔεΛՃ͢Δ ‣ 1SPNJTFܕͷϞδϡʔϧΛฦ͢
‣ ϝιουνΣʔϯ͔Β1SPNJTFΛฦ͢ ‣ 4VGpY͖ͷ͔ؔΒ1SPNJTFΛฦ͢ ݸਓత͓͢͢Ί -
4USFBNͱϑϩʔ੍ޚ૬ੑ͕ѱ͍ ͜Ε·Ͱ4USFBNΛϑϩʔ੍ޚʹΈࠐΉ߹ɺ1SPNJTF ͰแΈࠐΈϫϯγϣοτͷΠϯλʔϑΣʔεʹม͢Δ͔ɺ ಠࣗʹΠςϨʔγϣϯରԠͤ͞Δͱ͍͏ঢ়گͩͬͨɻ const recv = new Promise((resolve, reject)
=> { let data = '' stream.on('data', (chunk) => { data += chunk }) stream.once('end', () => { return resolve(data) }) stream.once(‘error', (err) => { return reject(err) }) }) const data = await recv() const drain = (stream) => { return new Promise((resolve, reject) => { stream.once('data', (data) => { stream.pause() … resolve(data) }) stream.once('end', () => { … resolve(null) }) stream.once('error', (err) => { … reject(err) }) stream.resume() }) } const main = async () => { const stream = fs.createReadStream(‘file’) let data = null while (data = await drain(stream)) { console.log(data) } } 1SPNJTFͰแΈࠐΉ ϫϯγϣοτม ෳࡶղͳ ΠςϨʔγϣϯରԠ -
4USFBNͷΤϥʔϋϯυϦϯάಠಛ 4USFBNͷجఈΫϥεͰ͋Δ&WFOU&NJUUFSͷΤϥʔϋϯυϦϯάಠಛͰ͋Γɺͦ ͷϋϯυϦϯά࿙ΕϓϩηεͷΫϥογϡʹ݁͢Δɻಛʹҙ͕ඞཁͳઃܭύλʔ ϯͷͻͱͭɻ ઃܭύλʔϯ ΤϥʔϋϯυϦϯά Ϋϥογϡ ඇಉظॲཧ $BMMCBDL if
(err) &WFOU&NJUUFS emitter.on(‘error') 1SPNJTF .catch() BTZODBXBJU try..catch .catch() ಉظॲཧ try..catch 1SPNJTFBTZODBXBJU -
"TZOD*UFSBUPSΛͬͨ4USFBNͷϑϩʔ੍ޚ stream.on('data', (data) => { console.log(data) }) stream.on('end', () =>
{ console.log('finished') }) stream.on(‘error', (err) => { console.error(err) }) try { for await (const data of stream) { console.log(data) } console.log(‘finished') } catch (err) { console.error(err) } 4USFBN "TZOD*UFSBUPS &4ͷػೳ"TZOD*UFSBUPSΛ׆༻͢Δ͜ͱͰɺ4USFBNΛγʔϜϨεʹϑϩʔ ੍ޚʹΈࠐΉ͜ͱ͕Ͱ͖ΔΑ͏ʹͳͬͨɻʢ&YQFSJNFOUBM"1*/PEFWʣ -
"TZOD*UFSBUPSΛͬͨ4USFBNͷϑϩʔ੍ޚ ςΩετϑΝΠϧΛߦ୯ҐͰॲཧͨ͠Γɺ)551ϦΫΤετͷDIVOLΛॲཧ͢Δ໘ͳ ͲͰ׆༻Ͱ͖Δɻ౷ҰతͳΤϥʔϋϯυϦϯά͕ඇৗʹັྗతɻ http.createServer(async (req, res) => { try {
let body = '' req.setEncoding('utf8') for await (const chunk of req) { body += chunk } console.log(body) res.end() } catch { res.statusCode = 500 res.end() } }) const main = async () => { const rl = readline.createInterface({ input: fs.createReadStream('input.txt') }) for await (const line of rl) { console.log(line) } } main().catch((err) => { console.error(err) }) ࣍ʹ໓͞ΕΔͷ4USFBN͔ʁ -
ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝ʢʣ ຊདྷελοΫτϨʔεσόοάͷॿ͚ʹͳΔͷ͕ͩɺඇಉظॲཧͷελοΫτϨʔ εʹཱͨͳ͍ɻඇಉظॲཧͷݺͼग़͠ݩɺඇಉظॲཧͷ։࢝Λ໋ྩͨ͠ίʔυͰ ͳ͘ΠϕϯτϧʔϓͰ͋ΔͨΊɺಠཱͨ͠ελοΫτϨʔε͕දࣔ͞Εͯ͠·͏ɻ const exec = require('child_process').exec const func
= (cb) => { exec('exit 1', (err) => { cb(err) }) } func((err) => { console.error(err) }) Error: Command failed: exit 1 at ChildProcess.exithandler at ChildProcess.emit at maybeClose at Socket.stream.socket.on at Socket.emit at Pipe._handle.close ࣮ߦ݁Ռ ݺͼग़͠ݩͷGVODؚ͕·Ε͓ͯΒͣ ΤϥʔͷൃੜՕॴ͕ಛఆͰ͖ͳ͍ -
ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝ʢʣ "TZOD'VODUJPOͷڥԼͰBXBJUʹΑͬͯελοΫτϨʔε͕͞ΕΔɻBXBJU Ͱதஅ͞ΕͨؔϚΠΫϩλεΫΩϡʔ͔Βॲཧ͕࠶։͞ΕΔͨΊɺલड़ͷͱಉ ༷ʹؔͷݺͼग़͠ܦ࿏͕ҡ࣋͞ΕͣɺΓ͞Εͯ͠·͏ɻ const func = async () =>
{ await 'interrupt' throw new Error('error') } const main = async () => { await func() } main().catch((err) => { console.error(err) }) Error: error at func at process._tickCallback at Function.Module.runMain at startup at bootstrapNodeJSCore ࣮ߦ݁Ռ ݺͼग़͠ݩͷNBJOؚ͕·Ε͓ͯΒͣ ΤϥʔͷൃੜՕॴ͕ಛఆͰ͖ͳ͍ -
ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝ʹରॲ͢Δ લड़ͨ͠ελοΫτϨʔεͷ՝ҎԼʹྻڍͨ͠ํ๏ʹΑͬͯରॲͰ͖Δɻ ํ๏ ֓ཁ JOTQFDUCSL$ISPNF%FW5PPMT w ༷ʑͳσόοάػೳΛแ w Φʔόʔϔου͋Γʢߴίετʣ BTZOD@IPPLTUSBDFDMBSJGZ
w ߴ͍Մಡੑͱ͍উखͷྑ͞ w Φʔόʔϔου͋Γ BTZODTUBDLUSBDFT w Φʔόʔϔουͳ͠ w BTZODBXBJUͷ՝ͷΈղܾՄೳ -
ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝ʹରॲ͢Δ BTZOD@IPPLTUSBDFDMBSJGZ USBDFϞδϡʔϧඪ४ϞδϡʔϧͷBTZOD@IPPLTΛར༻ͯ͠ɺඇಉظॲཧʹಠࣗίʔ υΛࠩ͠ࠐΈελοΫτϨʔεΛ֦ு͢ΔɻDMBSJGZϞδϡʔϧෆཁͳελοΫτϨʔ εΛআڈͯ͠ελοΫτϨʔεͷՄಡੑΛ্ͤ͞Δɻʢݸਓత͓͢͢Ίʣ ❯ node -r trace -r
clarify exec.js Error: Command failed: exit 1 at func at Object.<anonymous> ࣮ߦ݁Ռ ݺͼग़͠ݩͷGVODؚ͕·Ε ෆཁͳߦআ͞Ε͍ͯΔ const exec = require('child_process').exec const func = (cb) => { exec('exit 1', (err) => { cb(err) }) } func((err) => { console.error(err) }) -
ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝ʹରॲ͢Δ BTZODTUBDLUSBDFT 7Ҏ্ͷڥͰ͜ͷΦϓγϣϯΛ༗ޮʹ͢ΔͱɺBXBJUʹؚ·ΕΔใΛͬͯ ඇಉظॲཧΛލ͍ͩελοΫτϨʔε͕ߏங͞ΕΔΑ͏ʹͳΔɻ෦తͳղܾखஈ Ͱ͋Δ͕ɺ࣮ߦதͷγεςϜʹෛՙΛ༩͑ͳֵ͍৽తͳػೳɻ const func = async ()
=> { await 'interrupt' throw new Error('error') } const main = async () => { await func() } main().catch((err) => { console.error(err) }) ❯ node --async-stack-traces await.js Error: error at func at process._tickCallback at Function.Module.runMain at startup at bootstrapNodeJSCore at async main ࣮ߦ݁Ռ ݺͼग़͠ݩͷNBJOؚ͕·Ε͍ͯΔ ·ͩϑϥά͖ͷػೳɻࠓޙͷϑϥάղআʹظ