Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Callback to Promise and beyond

Callback to Promise and beyond

Daiki Kuriyama

February 01, 2019
Tweet

More Decks by Daiki Kuriyama

Other Decks in Technology

Transcript

  1. /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
  2. $BMMCBDLͱ1SPNJTFͷΠϯλʔϑΣʔεΛཱ྆ͤ͞Δ  $BMMCBDLΛলུͨ࣌͠ʹ1SPNJTFΛฦ͢  1SPNJTFઐ༻ͷΠϯλʔϑΣʔεΛ௥Ճ͢Δ  ‣ 1SPNJTFܕͷϞδϡʔϧΛฦ͢  ‣

    ϝιουνΣʔϯ͔Β1SPNJTFΛฦ͢  ‣ 4VGpY෇͖ͷؔ਺͔Β1SPNJTFΛฦ͢ Ϟδϡʔϧ಺Ͱ$BMMCBDLͱ1SPNJTFͷΠϯλʔϑΣʔεΛཱ྆ͤ͞Δํ๏ʹ͸͍ͭ͘ ͔ͷબ୒ࢶ͕͋ΓɺͦΕͧΕʹϝϦοτͱσϝϦοτ͕ଘࡏ͢Δɻ
  3. $BMMCBDLͱ1SPNJTFͷཱ྆ $BMMCBDLΛলུͨ࣌͠ʹ1SPNJTF͕ฦΔ // Callback func((data) => { console.log(data) }) //

    Promise const data = await func() console.log(data) ϚʔέοτΛௐࠪ͢ΔݶΓ͜ͷελΠϧͷ࠾༻ྫ͸ଟ͘ɺ+BWB4DSJQUͷจԽΛݟͯ΋ ύϥϝʔλΛলུͯ͠ڍಈ͕มΘΔ࢓૊Έ͸ଟ͘ଘࡏ͍ͯ͠Δɻ ϝιου͝ͱͷஈ֊తͳ1SPNJTFԽ͕ՄೳͰɺকདྷతͳ$BMMCBDLͷഇࢭ΋ࢹ໺ʹೖ Ε΍͍͢ɻͨͩ͠TFU5JNFPVU΍DIJME@QSPDFTTFYFDͷΑ͏ͳίʔϧόοΫؔ ਺Λड͚औΓɺಉ࣌ʹฦΓ஋΋ଘࡏ͢Δؔ਺ͱ͸૬ੑ͕ѱ͍ͨΊ஫ҙ͕ඞཁɻ
  4. $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ؔ਺ʹखΛՃ͑Δ ඞཁ͕ͳ͍ͱ͍͏ར఺΋͋Δɻ ͔͠͠Ϟδϡʔϧ಺ʹଘࡏ͢Δ͢΂ͯͷཁૉΛෳ੡ͯ͠վम͢Δඞཁ͕͋ΔͨΊɺରԠ ͷίετ͸վम࣌ʹूத͢Δɻ
  5. $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ͷഇࢭΛࢹ ໺ʹೖΕΔ৔߹͸ѻ͍͕೉͍͠ɻ
  6. $BMMCBDLͱ1SPNJTFͷཱ྆ 4VGpY෇͖ͷؔ਺͔Β1SPNJTFΛฦ͢ // Callback func((data) => { console.log(data) }) //

    Promise const data = await funcAsync() console.log(data) VUJMQSPNJTJGZ΍CMVFCJSEQSPNJTJGZ"MMͳͲΛར༻͢Δ͜ͱʹΑͬͯɺ࠷খݶ ͷίετͰϞδϡʔϧ಺ͷϝιουΛ1SPNJTFʹରԠ͢Δ͜ͱ͕Ͱ͖Δɻ কདྷతͳ$BMMCBDLͷഇࢭΛߟ͑Δ৔߹ɺޓ׵ੑʹͲ͏ରॲ͢Δ͔͕೰·͍͠ɻ4VGpYΛ ҡ࣋͢Δ͔ɺ·ͨ͸4VGpYΛআڈͯ͠1SPNJTFͷར༻ऀʹෛՙΛ༩͑Δ͔ͷબ୒͕ඞཁɻ
  7. 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ͰแΈࠐΉ ϫϯγϣοτม׵ ෳࡶ೉ղͳ ΠςϨʔγϣϯରԠ
  8. "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ʣ
  9. "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͔ʁ
  10. ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝୊ʢʣ ຊདྷελοΫτϨʔε͸σόοάͷॿ͚ʹͳΔ΋ͷ͕ͩɺඇಉظॲཧͷελοΫτϨʔ ε͸໾ʹཱͨͳ͍ɻඇಉظॲཧͷݺͼग़͠ݩ͸ɺඇಉظॲཧͷ։࢝Λ໋ྩͨ͠ίʔυͰ ͸ͳ͘ΠϕϯτϧʔϓͰ͋ΔͨΊɺಠཱͨ͠ελοΫτϨʔε͕දࣔ͞Εͯ͠·͏ɻ 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ؚ͕·Ε͓ͯΒͣ ΤϥʔͷൃੜՕॴ͕ಛఆͰ͖ͳ͍
  11. ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝୊ʢʣ "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ؚ͕·Ε͓ͯΒͣ ΤϥʔͷൃੜՕॴ͕ಛఆͰ͖ͳ͍
  12. ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝୊ʹରॲ͢Δ 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) })
  13. ඇಉظॲཧ๊͕͑ΔελοΫτϨʔεͷ՝୊ʹରॲ͢Δ 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ؚ͕·Ε͍ͯΔ ·ͩϑϥά෇͖ͷػೳɻࠓޙͷϑϥάղআʹظ଴