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

Callback to Promise and beyond

Callback to Promise and beyond

Avatar for Daiki Kuriyama

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ؚ͕·Ε͍ͯΔ ·ͩϑϥά෇͖ͷػೳɻࠓޙͷϑϥάղআʹظ଴