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

Minimum Hands-on Node.js / minimum handson nodejs

Minimum Hands-on Node.js / minimum handson nodejs

Daiki Kuriyama

November 29, 2019
Tweet

More Decks by Daiki Kuriyama

Other Decks in Programming

Transcript

  1. .JOJNVN)BOETPO/PEFKT
    ձ৔ 3PPN#
    ೔࣌
    2019೥12݄01೔ 14:15ʙ16:00
    ్த15෼ͷٳܜΛڬΈ·͢
    ϋογϡλά #jsconfjp_b
    εϐʔΧʔ
    ɹɹɹ܀ࢁଠرʢ!"KJEPʣ
    ɹɹɹϠϑʔגࣜձࣾ›/PEFKTࠇଳ

    View Slide

  2. .*/*.6.)"/%40//0%&+4 / 53
    ௌߨର৅ऀ▶︎+BWB4DSJQUͳΒগ͠Θ͔Δ͚ΕͲ/PEFKT͸͍·ͻͱͭͱ͍͏ํ
    ಘΒΕΔ෺▶︎ࠓ͙͢࢖͑Δ/PEFKTͷجૅ஌ࣝ
    ͜ͷࢿྉͷϦϯΫ https://speakerdeck.com/ajido/minimum-handson-nodejs
    ԋशϦϯΫ
    https://chouseisan.com/s?h=4a0d7eb9c38a440e9ad585abfbb16e79
    ‣ bit.ly/2XWSQQK
    εΫϦϓτϦϯΫ https://github.com/ajido/nodejs-handson
    ϋϯζΦϯதʹ্هϦϯΫϖʔδΛར༻͠·͢ɻࣄલʹ֬͝ೝ͍ͩ͘͞
    !
    2

    View Slide

  3. +BWB4DSJQU
    &4 &4ʙ 5ZQF4DSJQU
    ֶशϚοϓ
    ηΩϡΞϓϩάϥϛϯά
    / 53
    04
    104*9
    8)"58("1*
    %0. FUD
    'SPOUFOE
    'SBNFXPSLT
    8FC
    'SBNFXPSLT
    1BB4 $BB4 'BB4
    /PEFKT$PSF"1*
    )551)5514
    5$1*1
    ˔ࠓճͷϋϯζΦϯ಺༰
    5PPMT
    %# 5FTU -PHFUD
    !
    3

    View Slide

  4. جૅ Ԡ༻
    ‣ Πϯετʔϧ 5 ‣ ϑϩʔ੍ޚ 38
    ‣ Ϟδϡʔϧ؅ཧ 11 ‣ ඇಉظؔ਺ 42
    ‣ ಛ௃ 16 ‣ σόοά
    ‣ σβΠϯύλʔϯ 21 ‣ Ϟδϡʔϧͷ࡞੒
    ‣ ίʔϧόοΫ 23 ‣ ϓϩϑΝΠϦϯά
    ‣ Πϕϯτۦಈ 31 ‣ ϑϨʔϜϫʔΫͱπʔϧ
    ‣ ಉظॲཧ 35

    View Slide

  5. Πϯετʔϧ
    OPEFKTPSH͔ΒΠϯετʔϧ͠·͢ɻ-54ͱ$VSSFOUͷ͏ͪɺ௕ظؒͷϝϯςφϯ
    ε͕อূ͞ΕɺՄೳͳݶΓޓ׵ੑ͕ҡ࣋͞ΕΔ-54όʔδϣϯΛબ୒͍ͯͩ͘͠͞ɻ
    ฐࣾͰ͸ιʔείʔυϏϧυͯ͠31.ύο
    έʔδʹ͍ͯ͠·͢ɻͦͷࡍύοέʔδϨ
    δετϦΛࣾ಺ʹ޲͚ͯηΩϡϦςΟରࡦ
    ͕ߦ͑ΔΑ͏ʹ͍ͯ͠·͢ɻ
    -54όʔδϣϯΛબ୒
    IUUQTOPEFKTPSH
    -54 ۮ਺ ϲ݄
    $VSSFOU ح਺ ϲ݄
    !
    5 / 53

    View Slide

  6. දࣔͰ͖ͨΒɺ

    ԋशϦϯΫͷϖʔδΛ։͘

    ʮग़ܽΛೖྗ͢ΔʯΛԡ͢

    ࠓճ͸ԋशςετͳͷͰʮԋशςετʯͷ߲໨Λº͔Β⚪ʹมߋ͢Δ

    ʮೖྗ͢ΔʯΛԡͯ͠ɺԋशΛ׬ྃ͢Δ

    λʔϛφϧͰ/PEFKTͷόʔδϣϯΛද͍ࣔͯͩ͘͠͞ɻ
    $ node -v
    v12.13.1
    ԋशςετ
    ԋशϦϯΫ
    https://chouseisan.com/s?h=4a0d7eb9c38a440e9ad585abfbb16e79
    ‣ bit.ly/2XWSQQK
    ͜ͷࢿྉͷϦϯΫ https://speakerdeck.com/ajido/minimum-handson-nodejs
    !
    6 / 53

    View Slide

  7. ඪ४Ϟδϡʔϧʢ$PSF"1*ʣ
    /PEFKT͸(PPHMF$ISPNFʹ࠾༻͞Ε͍ͯΔ7+BWB4DSJQUΤϯδϯͱɺඪ४ͷ
    +BWB4DSJQUʹ͸ͳ͍֤छ࣮૷͕૊Έ߹ΘͤΒΕͨ+BWB4DSJQUͷ࣮ߦ؀ڥͰ͢ɻ
    const fs = require(‘fs')
    fs.readFile(__filename, (err, data) => {
    console.log(data)
    })
    ͜͜Ͱͷඪ४Ϟδϡʔϧͱ͸ɺ/PEFKTʹ૊Έࠐ·Εͨʮඪ४ͷ+BWB4DSJQUʹ͸ͳ͍
    ֤छ࣮૷ʯͷ͜ͱΛࢦ͠·͢ɻ
    __filename͸ࣗ਎ͷεΫϦϓτ
    ϑΝΠϧͷઈରύεͰ͢ɻ
    !
    7 / 53

    View Slide

  8. ඪ४Ϟδϡʔϧʢ$PSF"1*ʣ
    fs ϑΝΠϧΛ࡞੒ɾ࡟আ͢Δ
    path ϑΝΠϧύεɾσΟϨΫτϦύεΛѻ͏
    http )551αʔόɾΫϥΠΞϯτΛ࣮૷͢Δ
    crypto ϋογϡɾ҉߸ɾॺ໊ɾݕূͳͲͷ҉߸ػೳΛѻ͏
    util ϢʔςΟϦςΟϞδϡʔϧ
    querystring 63-ΫΤϦจࣈྻΛύʔε͢Δ
    os $16ͷ਺΍ϗετ໊ͳͲͷ04ؔ࿈৘ใΛࢀর͢Δ
    child_process ࢠϓϩηεΛ࡞੒͢Δ
    cluster αʔόΛϚϧνϓϩηεԽ͢Δ
    assert ม਺ͷ಺༰΍ॲཧͷԠ౴ΛνΣοΫ͢Δ
    ΧςΰϦ جຊతͰଞʹґଘੑͷͳ͍"1*
    Events, Modules, Buffer, Stream
    ΧςΰϦ /PEFݻ༗ͷ΋ͷͰຊମͷಈ࡞ʹؔ࿈͢Δ"1*
    Timers, Process, Console
    ΧςΰϦ 04ͷػೳ΍ଞͷϥΠϒϥϦͱؔ࿈͢Δ"1*
    File System, Net, UDP/Datagram, TLS/SSL, Child Processes
    ΧςΰϦ ΞϓϦέʔγϣϯ޲͚ͷԠ༻"1*
    HTTP, HTTPS, Cluster
    IUUQTOPEFKTPSHEJTUMBUFTUEPDTBQJEPDVNFOUBUJPOIUNM
    ֤छඪ४Ϟδϡʔϧͱͦͷ༻్ͷҰྫ جఈΦϒδΣΫτผʹΧςΰϥΠζͨ͠ਤɻ
    ΧςΰϦ͔Βॱʹֶश͢Δ͜ͱͰɺΑΓཧղ͕ਂ·Γ·͢
    !
    8 / 53

    View Slide

  9. 3&1-
    /PEFKTͷର࿩తΠϯλʔϑΣʔεͰ͢ɻ3&1-ʢ3FBE&WBM1SJOU-PPQʣ؀ڥͰ
    ͸ඪ४Ϟδϡʔϧ͕ࣗಈతʹϩʔυ͞ΕΔͨΊɺͦΕΒΛಡΈࠐΉ͜ͱͳ͘ѻ͑·͢ɻ
    $ node
    > /^\d+$/.test(‘1024’)
    true
    // requireすることなく標準モジュールを呼び出せます
    > os.hostname()
    ‘MAC-Z-941.local’
    > .exit
    ίʔυͷ͢͹΍͍ݕূʹ໾ཱͪ·͢ɻԋशத΋ੋඇ׆༻ͯ͠Έ͍ͯͩ͘͞ɻ
    3&1-ͷऴྃ͸-D ΛૹΔ͔
    .exit ͱೖྗ͍ͯͩ͘͠͞ɻ
    ͦͷଞίϚϯυ͸.helpΛࢀর
    !
    9 / 53

    View Slide


  10. ࣗ਎ͷ୺຤ͷ$16ίΞͷ਺Λɺඪ४Ϟδϡʔϧͱ3&1-Λ࢖ͬͯද͍ࣔͯͩ͘͠͞ɻ
    $ node
    > 䡧䡧䡧䡧䡧䡧䡧䡧䡧
    [ { model: 'Intel(R) Core(TM) i5-5287U CPU @ 2.90GHz',
    speed: 2900,
    times: { user: 78882290, nice: 0, sys: 63998990, idle: 611174200, irq: 0 } },
    ... ]
    > 䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧䡧
    4
    ԋश
    ͜ͷࢿྉͷϦϯΫ https://speakerdeck.com/ajido/minimum-handson-nodejs
    ԋशϦϯΫ
    https://chouseisan.com/s?h=4a0d7eb9c38a440e9ad585abfbb16e79
    ‣ bit.ly/2XWSQQK
    εΫϦϓτϦϯΫ https://github.com/ajido/nodejs-handson
    3&1-ͷऴྃ͸-D ΛૹΔ͔
    .exit ͱೖྗ͍ͯͩ͘͠͞ɻ
    ͦͷଞίϚϯυ͸.helpΛࢀর
    !
    10 / 53

    View Slide

  11. جૅ›Ϟδϡʔϧ؅ཧ

    View Slide

  12. OQN
    OQN /PEF1BDLBHF.BOBHFS
    ͸OQN *ODʹΑΓ؅ཧɾఏڙ͞Ε͍ͯΔ/PEFKT૊Έ
    ࠐΈͷύοέʔδ؅ཧγεςϜͰ͢ɻੈքத͔Βར༻͞ΕΔதԝϨδετϦͷOQNKTDPNʹ
    ͸ଟ਺ͷϞδϡʔϧ͕ެ։͞Ε͍ͯ·͢ɻ
    ಺༰ όʔδϣϯ؅ཧ
    node_modules Ϟδϡʔϧͷ࣮ମɾιʔείʔυ
    package-lock.json Πϯετʔϧ͞ΕͨϞδϡʔϧͷπϦʔ৘ใ ✔
    package.json
    ύοέʔδͷϝλσʔλ
    ϓϩδΣΫτʹ௚઀ґଘ͢ΔϞδϡʔϧͷ؅ཧσʔλͳͲ

    ۮൃతͳύοέʔδͷެ։Λ๷͙ͨΊʹ
    package.jsonʹprivate:trueΛ௥هͯ͠
    ͍ͩ͘͞ɻ
    ͜ͷΦϓγϣϯΛ༗ޮʹ͢Δ͜ͱͰɺຊདྷ
    package.jsonʹهड़͠ͳ͚Ε͹ͳΒͳ͍֤छ
    ৘ใΛলུ͢Δ͜ͱ΋Ͱ͖·͢ɻ
    package-lock.json͕͋Ε͹node_modules
    σΟϨΫτϦ͸෮ݩͰ͖·͢ɻnode_modules͸
    όʔδϣϯ؅ཧͷର৅͔Β֎͍ͯͩ͘͠͞ɻ
    !
    12 / 53
    // プロジェクトを新規作成する
    $ npm init
    $ npm install request
    $ ls
    ├── node_modules
    ├── package.json
    └── package-lock.json

    View Slide


  13. npminitίϚϯυͰpackage.jsonΛ࡞੒ͨ͋͠ͱrequestϞδϡʔϧΛΠϯε
    τʔϧ͍ͯͩ͘͠͞ɻͦͷޙrequestϞδϡʔϧΛ࢖ͬͯ)551ϦΫΤετΛૹΓɺ
    εςʔλείʔυΛද͍ࣔͯͩ͘͠͞ɻ
    const request = require('request')
    request('https://www.yahoo.co.jp', (err, res, body) => {
    console.log(res.statusCode)
    })
    ԋश
    ԋशϦϯΫ
    https://chouseisan.com/s?h=4a0d7eb9c38a440e9ad585abfbb16e79
    ‣ bit.ly/2XWSQQK
    εΫϦϓτϦϯΫ https://github.com/ajido/nodejs-handson
    $ npm init
    $ npm install request
    !
    13 / 53

    View Slide

  14. ηϚϯςΟοΫόʔδϣχϯά
    ."+03
    ޙํޓ׵ੑΛࣦ͏ͱ͖ʹΠϯΫϦϝϯτ͞ΕΔ
    ͦͷࡍ.*/03ͱ1"5$)Λʹ͢Δ
    .*/03
    ޙํޓ׵ੑ͕͋ΓɺػೳΛ௥Ճͨ͠ͱ͖ʹΠϯΫϦϝϯτ͞ΕΔ
    ͦͷࡍ1"5$)Λʹ͢Δ
    1"5$) ޙํޓ׵ੑ͕͋ΓɺόάΛमਖ਼ͨ͠ͱ͖ʹΠϯΫϦϝϯτ͞ΕΔ
    ?
    ."+03.*/031"5$)
    ?ه߸͸ύοέʔδͷόʔδϣϯൣғΛࢦఆ͓ͯ͠Γɺࠨଆͷ
    ஋Ͱ͸ͳ͍਺஋Λݻఆ͢Δ͜ͱΛද͍ͯ͠·͢ɻ͜Ε͸ഁյతͳ
    มߋΛආ͚ͨ߹ཧతͳΞοϓσʔτΛߦ͏͜ͱΛҙຯ͠·͢ɻ
    OQNύοέʔδ͸͜ͷ࢓༷
    ʹ४ڌͨ͠όʔδϣϯ؅ཧ͕
    ਪ঑͞Ε͍ͯ·͢ɻ
    ύοέʔδར༻ऀ΋جຊతʹ
    ͸ηϚϯςΟοΫόʔδϣχ
    ϯάΛ೦಄ʹύοέʔδΛ؅
    ཧ͍ͯͩ͘͠͞ɻ
    !
    14 / 53

    View Slide

  15. Ϟδϡʔϧ؅ཧϫʔΫϑϩʔ
    $ npm init
    // 必要なら private: true を追加
    $ npm install
    // ツリー情報から node_modules を再構築
    $ npm ci
    $ npm audit
    $ npm audit fix
    $ npm outdated
    $ npm update / npm install @
    ϓϩδΣΫτΛ৽ن࡞੒͢Δ৔߹ طଘͷϓϩδΣΫτʹՃΘΔ৔߹
    ੬ऑੑνΣοΫ
    ύοέʔδͷߋ৽νΣοΫɾ௥Ճ
    !
    15 / 53

    View Slide

  16. جૅ›ಛ௃

    View Slide

  17. ಛ௃ͱ஫ҙ఺
    /PEFKTͷαʔόʔ͸γϯάϧϓϩηεɾγϯάϧεϨουͰେྔͷϦΫΤετΛॲཧ͠·͢ɻ͜
    ͷ؍఺͔Βɺ·ͣ͸04ͷϓϩηε͋ͨΓͷϑΝΠϧσΟεΫϦϓλ਺ͷ੍ݶʹ஫ҙ͍ͯͩ͘͠͞ɻ
    # 初期値では明らかに足りません
    $ ulimit -n
    1024

    [Service]
    LimitNOFILE=65536
    ॳظ஋ͷ··ϓϩμΫγϣϯ؀ڥͰϦΫΤετΛड͚෇͚ͯ͠·͏ͱɺߴ͍τϥϑΟοΫΛॲཧ
    ࢝͠ΊͨࡍʹToo many open filesʹΑΔϓϩηεμ΢ϯ͕΄΅࣮֬ʹൃੜ͠·͢ɻ
    $ ulimit -n 65536
    $ ulimit -n
    65536
    ulimit -nʹΑΔ੍ݶͷ্ॻ͖ TZTUFNEʹΑΔ੍ݶͷઃఆ
    ัଊϚϧνίΞ͕׆༻Ͱ͖Δ؀ڥͰ͸Ұൠ
    తʹclusterϞδϡʔϧΛ࢖ͬͯϚϧνϓ
    ϩηεԽ͠·͢ɻ
    !
    17 / 53

    View Slide

  18. Πϕϯτϧʔϓ
    /PEFKT͕େྔͷτϥϑΟοΫΛॲཧ͠ଓ͚Δ؀ڥΛҡ࣋͢ΔͨΊʹ͸ɺΠϕϯτϧʔϓΛՄೳ
    ͳݶΓࢭΊͣʹӡ༻͢Δ͜ͱ͕΋ͬͱ΋ॏཁͰ͢ɻ͜ͷΠϕϯτϧʔϓ͕ͳʹ͔Λઆ໌͢Δલ
    ʹɺ·ͣ͸Πϕϯτϧʔϓ͕؆୯ʹࢭ·ͬͯ͠·͏࣮૷ྫΛྻڍ͠·͢ɻ
    ϑΝΠϧ΍ωοτϫʔΫॲཧΛ൐Θͳ͍$16Λ௕࣌ؒ઎༗͠ଓ͚Δॲཧͱɺ଴ػ࣌ؒͷ௕͍ಉظతͳ
    "1*Λར༻͢Δ͜ͱͰɺΠϕϯτϧʔϓ͸க໋తͳ·Ͱʹఀࢭ͠·͢ɻ
    ͋Γ͕ͪ౓ ΠϕϯτϧʔϓΛ௕࣌ؒఀࢭͤ͞Δ࣮૷ͷҰྫ
    ⚠⚠⚠ ਺ඦ,#Ҏ্ͷڊେͳ+40/σʔλΛॲཧ͢Δ
    ⚠⚠ GTϞδϡʔϧͷಉظؔ਺Λ࢖͏
    ⚠ ϧʔϓΛճ͠ଓ͚Δ
    ܦݧ্ɺڊେͳ+40/ͷύʔεʹΑΔ
    ύϑΥʔϚϯεྼԽ͕ඇৗʹଟ͍ɻ
    !
    18 / 53

    View Slide

  19. Πϕϯτϧʔϓ
    const http = require('http')
    http.createServer((req, res) => {
    // この部分の記述次第でパフォーマンスが劇的に変化する
    res.end()
    }).listen(8080)
    Πϕϯτϧʔϓ͸/PEFKTʹ͓͚Δ಄೴ͷΑ͏ͳ΋ͷͰɺ༩͑ΒΕ໋ͨྩΛॱ࣮࣍ߦ͢
    ΔίΞͰ͢ɻ͜ΕΛҰ੾ఀࢭͤ͞ͳ͍ͱ͍͏͜ͱ͸ෆՄೳͰ͕͢ɺఀࢭ࣌ؒΛஅଓత͔
    ͭ࠷খݶʹ཈͑ଓ͚Δ͜ͱͰɺ/PEFKT͸εϜʔζʹϦΫΤετΛॲཧ͠ଓ͚Δ͜ͱ͕
    Ͱ͖·͢ɻ
    $ vegeta attack -duration=10s -rate=0 -max-workers=100
    ॲཧͷ಺༰ 314
    ͳ͠
    JSON.parse 20KB
    JSON.parse 500KB
    fs.readFile 1MB
    fs.readFileSync 1MB
    forEach Loop 100
    forEach Loop 100,000
    !
    19 / 53

    View Slide

  20. +40/σʔλͷ࠷దͳαΠζ͸ʁ
    ୯७ͳߏ଄ͷ+40/σʔλΛύʔεͨ͠ͱ͖ͷΠϕϯτϧʔϓͷఀࢭ࣌ؒ
    0ms
    50ms
    100ms
    150ms
    200ms
    100KB 300KB 500KB 700KB 900KB 2M 4M 6M 8M 10M 30M 50M
    ࠷దͳ஋͸༩͑ΒΕΔσʔλ΍ΞϓϦέʔγϣϯʹԠ࣮ͨ͡ࢪࢼݧʹΑׂͬͯΓग़͢΂͖Ͱ͕͢ɺ
    ໨҆ͱͯ͠͸ʮʢΑ΄Ͳେ͖ͯ͘΋ʣ࠷େ.ʹऩ·Δʯ͜ͱΛ೦಄ʹʮ࣌ؒܦա΍γεςϜͷ੒௕ʹ
    ൐͍+40/ͷαΠζ͕ංେԽ͠ͳ͍ʯ͜ͱͱʮϚϧνϓϩηεԽ͢Δʯ͜ͱʹཹҙ͍ͯͩ͘͠͞ɻ
    !
    20 / 53
    ‑ڐ༰ൣғ
    ‑ݶք

    View Slide

  21. σβΠϯύλʔϯ

    View Slide

  22. σβΠϯύλʔϯ
    /PEFKT͸ΠϕϯτϧʔϓΛఀࢭͤ͞ΔՄೳੑ͕͋Δॲཧͷେ෦෼Λඇಉظॲཧͱ͢Δ
    ͜ͱͰɺޮ཰తʹτϥϑΟοΫΛॲཧ͠·͢ɻ͜ͷಛੑʹج͍ͨ/PEFKTͷಛ௃త͔ͭ
    جૅతͳೋͭͷσβΠϯύλʔϯΛֶͼ·͢ɻ
    !
    22 / 53

    View Slide

  23. σβΠϯύλʔϯ›ίʔϧόοΫ

    View Slide

  24. ίʔϧόοΫ
    Լه͸ͲͪΒ΋ϑΝΠϧΛಡΈࠐΈग़ྗ͍ͯ͠·͢ɻϑΝΠϧͷಡΈࠐΈʹfs.readFileSyncΛར
    ༻ͨ͠৔߹͸ಉظతͳॲཧͱͳΓɺಡΈࠐΈ׬ྃ·ͰΠϕϯτϧʔϓΛࢭΊͯ͠·͍·͕͢ɺ
    fs.readFileΛར༻͢ΔͱඇಉظతͳॲཧͱͳΓɺಡΈࠐΈ׬ྃ·ͰͷؒɺଞͷॲཧʹϦιʔεΛ
    ׂΓ౰ͯΔ͜ͱ͕Ͱ͖·͢ɻ
    // 非同期 … 読み込み中イベントループが停止しない。完了後にコールバック関数が呼び出される
    const fs = require(‘fs')
    fs.readFile(__filename, (err, data) => {
    console.log(data.toString())
    })
    // 同期 … ファイル読み込み中イベントループが停止する
    const fs = require(‘fs')
    const data = fs.readFileSync(__filename).toString()
    console.log(data)
    !
    24 / 53

    View Slide

  25. ίʔϧόοΫͷ׳ྫ
    ίʔϧόοΫؔ਺͸جຊతʹෳ਺ճݺͼग़͞ΕΔ͜ͱ͸͋Γ·ͤΜɻྫ֎͸͋Γ·͕͢ɺඇ
    ಉظॲཧͷ׬ྃޙʹҰ౓͚ͩݺͼग़͞Ε·͢ɻͦͯ͠ݺͼग़͞ΕͨίʔϧόοΫؔ਺ͷୈҰ
    Ҿ਺ʹ͸ɺॲཧ͕੒ޭ͔ͨ͠Ͳ͏͔Λද͢ΤϥʔΦϒδΣΫτ͕ฦΓ·͢ɻ
    ίʔϧόοΫύλʔϯͷ׳ྫ
    "1*ͷ࠷ޙͷҾ਺͕ίʔϧόοΫؔ਺
    fs.readFile(path[, options], callback)
    ॲཧͷ׬ྃޙʹίʔϧόοΫؔ਺͕Ұ౓͚ͩݺͼग़͞ΕΔ
    ݺͼग़͞ΕͨίʔϧόοΫؔ਺ͷୈҰҾ਺͕ඇಉظॲཧͷࣦഊΛද͢ΤϥʔΦϒδΣΫτ
    fs.readFile(__filename, (err, data) => {
    console.log(data.toString())
    })
    !
    25 / 53

    View Slide

  26. ίʔϧόοΫͷΤϥʔϋϯυϦϯά
    ίʔϧόοΫؔ਺ͷୈҰҾ਺͕ΤϥʔΦϒδΣΫτͰ͢ɻΤϥʔϋϯυϦϯά͸ୈҰҾ਺
    ͷΤϥʔΦϒδΣΫτͷOVMMνΣοΫΛߦ͍ɺOVMMͰͳ͍৔߹͸ΤϥʔΛॲཧͯ͘͠
    ͍ͩ͞ɻ
    const fs = require('fs')
    fs.readFile(__filename, (err, data) => {
    if (err) {
    console.error(err)
    return
    }
    console.log(data)
    })
    Τϥʔͷதʹ͸ແࢹ͢ΔʢʹϋϯυϦϯά
    ͠ͳ͍ʣ͜ͱͰϓϩηε͕Ϋϥογϡͯ͠
    ͠·͏΋ͷ΋ଘࡏ͠·͕͢ɺίʔϧόοΫ
    ୈҰҾ਺ͷΤϥʔ͸ແࢹͯ͠΋ϓϩηε͕
    Ϋϥογϡ͢Δ͜ͱ͸͋Γ·ͤΜɻ
    !
    26 / 53

    View Slide

  27. ίʔϧόοΫͷΑ͋͘Δࣦഊྫ
    returnͷॻ͖๨Ε
    // 誤
    const fs = require('fs')
    fs.readFile(__filename, (err, data) => {
    if (err) console.error(err)
    console.log(data)
    })
    // 正
    const fs = require('fs');
    fs.readFile(__filename, (err, data) => {
    if (err) return console.error(err)
    console.log(data)
    })
    !
    27 / 53
    ҟৗܥͷॲཧͷ͋ͱਖ਼ৗܥͷॲཧ΋
    ૸ͬͯ͠·͍·͢ɻ

    View Slide

  28. ίʔϧόοΫͷΑ͋͘Δࣦഊྫ
    try/catchΛ࢖ͬͯඇಉظॲཧͷΤϥʔΛั·͑Δ
    // 誤
    const fs = require('fs')
    try {
    fs.readFile(__filename, (err, data) => {
    console.log(data)
    })
    } catch (err) {
    console.error(err)
    }
    // 正
    const fs = require('fs')
    fs.readFile(__filename, (err, data) => {
    if (err) return console.error(err)
    console.log(data)
    })
    ͨͩ͠ඇಉظॲཧͷલஈ֊ͷΤϥʔ͸͜ͷtry/catchʹΑͬͯิ଍Ͱ͖·͢ɻ
    ͦͷͨΊ͜ͷɹ
    try/catch΋ݫີʹ͸ඞཁͱݴ͑Δ͜ͱʹ஫ҙ͍ͯͩ͘͠͞ɻ
    !
    28 / 53

    View Slide

  29. ίʔϧόοΫͷΑ͋͘Δࣦഊྫ
    ඇಉظॲཧͷಉظతͳϧʔϓ
    // 誤
    const fs = require('fs')
    for (let i = 0; i < 100; i++) {
    fs.appendFile('./data.txt', i + ',', (err) => {
    })
    }
    // 0,3,4,5,6,7,8,9,10,11,12,20,21,1,2,28,3,4,5,6,7,8...
    // 再帰処理による対処の一例(必ずしも正解というわけではありません)
    const write = (i) => {
    if (i === 100) return
    fs.appendFile('./data.txt', i + ',', (err) => {
    write(++i)
    })
    }
    write(0)
    0-99ͷ਺஋ΛॱʹϑΝΠϧʹॻ͖ࠐΉ͜ͱΛҙ
    ਤͯ͠ϧʔϓ͍ͯ͠·͕͢ɺ࣮ࡍ͸ʮ΄΅ಉ࣌ʹ
    0-99ͷ਺஋ΛϑΝΠϧʹॻ͖ࠐΉʯॲཧʹͳͬ
    ͍ͯ·͢ɻ͜ͷͨΊ݁Ռ͸ॱෆಉͳ਺஋ͷฒͼʹ
    ͳΓ·͢ɻ
    !
    29 / 53

    View Slide

  30. σβΠϯύλʔϯ›Πϕϯτۦಈ

    View Slide

  31. Πϕϯτۦಈ
    ඇಉظॲཧͱͷ਌࿨ੑ͕ߴ͍΋͏ͻͱͭͷσβΠϯύ
    λʔϯ͕ΠϕϯτۦಈͰ͢ɻ/PEFKTͷΠϕϯτۦ
    ಈύλʔϯ͸EventEmitterͱ͍͏جఈΫϥεΛ
    ೚ҙͷΦϒδΣΫτʹܧঝͤ͞Δ͜ͱͰ࣮૷͠·͢ɻ
    const Redis = require('ioredis')
    const redis = new Redis()
    const stream = redis.scanStream({
    match: '*',
    count: 100
    })
    // 約100件のキーを読み込むごとに呼び出される
    stream.on('data', (keys) => {
    for (const key of keys) {
    console.log(key)
    }
    })
    // 全てのキーを走査した後に呼び出される
    stream.on('end', () => {
    console.log(‘end')
    })
    ,74ʹ઀ଓͯ͠ΩʔͷҰཡΛྻڍ͢ΔΠϕϯτۦಈܕͷίʔυ
    EventEmitter Λܧঝͨ͠
    ΠϕϯτۦಈܕͷΦϒδΣΫτ
    ίʔϧόοΫͱͷҧ͍
    ॲཧͷ׬ྃʹݶΒͣɺॲཧͷ్தɾ։࢝ɾऴྃͳͲɺ
    ঢ়ଶͷมԽΛද༷͢ʑͳλΠϛϯάͰॲཧΛڬΈࠐΉ͜ͱ͕Ͱ͖Δ
    ঢ়ଶͷมԽΛද͢ʮΠϕϯτʯ͸Կ౓΋܁Γฦ͠ൃੜ͠ɺ
    ͦͷ౓ʹରԠ͢ΔϦεφʔؔ਺͕ݺͼग़͞ΕΔ
    ,74ʹ਺͑੾Εͳ͍ྔͷΩʔ͕ଘࡏ͍ͯͨ͠ͱͯ͠΋ɺ݅୯ҐͰॲཧ
    ͍ͯ͠ΔͨΊɺϝϞϦΛѹഭ͢Δ͜ͱͳ͘ɺΠϕϯτϧʔϓΛ௕࣌ؒఀࢭ͞
    ͤΔ͜ͱ΋͋Γ·ͤΜɻ
    !
    31 / 53

    View Slide

  32. ΠϕϯτۦಈͷΤϥʔϋϯυϦϯά
    ΠϕϯτۦಈܕͷΠϯλʔϑΣʔεΛ࣋ͬͨΦϒδΣ
    ΫτͷΤϥʔΠϕϯτʹϦεφʔؔ਺Λ௥Ճ͠·͢ɻ
    const Redis = require('ioredis')
    const redis = new Redis()
    const stream = redis.scanStream({
    match: '*',
    count: 100
    })
    // 約100件のキーを読み込むごとに呼び出される
    stream.on('data', (keys) => {
    for (const key of keys) {
    console.log(key)
    }
    })
    // 全てのキーを走査した後に呼び出される
    stream.on('end', () => {
    console.log(‘end')
    })
    // 何かしらエラーが発生した時に呼び出される
    stream.on('error', (err) => {
    console.error(err)
    })
    ΠϕϯτۦಈܕͷΦϒδΣΫτΛݟ෼͚Δώϯτ
    ˞ඞͣ͠΋੒ཱ͢Δ৚݅Ͱ͸͋Γ·ͤΜ
    υΩϡϝϯτʹൃੜ͢ΔΠϕϯτ͕هࡌ͞Ε͍ͯΔ
    .onϝιου͕ଘࡏ͢Δ
    streamͱ͍͏໊শ͕࢖ΘΕ͍ͯΔ
    ΦϒδΣΫτ͕Πϕϯτۦಈܕ͔Ͳ͏͔͸ɺओʹυΩϡϝϯτ͔Β൑அ͠·
    ͢ɻͦͯ͠ΠϕϯτۦಈܕͷΠϯλʔϑΣʔεͰ͋ͬͨ৔߹͸on(error)
    Λ࢖ͬͯΤϥʔॲཧΛ௥Ճ͍ͯͩ͘͠͞ɻ
    emitter.on('error', (err) => {
    console.error(err)
    })
    !
    32 / 53

    View Slide

  33. ΠϕϯτۦಈͷΑ͋͘Δࣦഊྫ
    on('error')ͷϋϯυϦϯά࿙ΕͱͦΕʹ൐͏ϓϩηεͷΫϥογϡ
    // 誤
    const fs = require('fs')
    const rs = fs.createReadStream(__filename)
    rs.on('data', (data) => {
    console.log(data)
    })
    // 正
    const fs = require('fs')
    const rs = fs.createReadStream(__filename)
    rs.on('data', (data) => {
    console.log(data)
    })
    rs.on('error', (err) => {
    console.error(err)
    })
    ΠϕϯτۦಈܕͷΤϥʔϋϯυϦϯά͸୭΋͕๨Ε͕ͪͰ͢ɻϋϯυϦϯάΛ๨ΕΔͱΤϥʔ
    ൃੜ࣌ʹϓϩηε͕Ϋϥογϡͯ͠͠·͏ͨΊɺࡉ৺ͷ஫ҙΛ෷͏ඞཁ͕͋Γ·͢ɻ
    !
    33 / 53

    View Slide

  34. ಉظॲཧ

    View Slide

  35. ಉظॲཧͱඇಉظॲཧΛݟ෼͚Δʹ͸ʁ
    const data = Buffer.alloc(1024 * 1024 * 1024)
    data.forEach((value) => {
    console.log(value)
    })
    ͜Ε·Ͱඇಉظॲཧʹదͨ͠σβΠϯύλʔϯͱɺͦΕʹରԠ͢ΔΤϥʔϋϯυϦϯάΛղઆ
    ͠·͕ͨ͠ɺ࠷ޙʹಉظॲཧʹ͍ͭͯ঺հ͠·͢ɻ·ͣಉظॲཧͱඇಉظॲཧΛݟ෼͚Δํ๏
    Ͱ͕͢ɺද໘తͳ৘ใ͔Β࣮֬ʹ൑அ͢Δํ๏͸͋Γ·ͤΜɻͰ͕͢ҎԼʹώϯτͱͳΔ৘ใ
    Λྻڍ͠·͢ɻ
    ඇಉظॲཧΛݟ෼͚Δώϯτ˞ඞͣ͠΋੒ཱ͢Δ৚݅Ͱ͸͋Γ·ͤΜ
    ωοτϫʔΫ·ͨ͸ϑΝΠϧΛѻ͏
    "1*ͷ࠷ޙͷҾ਺͕callbackͰ͋Γɺ"1*ͷ໊শʹSync͕෇͍͍ͯͳ͍
    1SPNJTFΦϒδΣΫτΛฦ͢
    !
    35 / 53
    ίʔϧόοΫؔ਺Λड͚औΔ"1*Ͱ͕͢
    ಉظॲཧͰ͢ɻίʔϧόοΫʹඇಉظॲ
    ཧͱ͍͏Θ͚Ͱ͸͋Γ·ͤΜ

    View Slide

  36. ಉظॲཧͷΤϥʔϋϯυϦϯά
    ಉظॲཧ͸্͔ΒॱʹίʔυΛ࣮ߦͯ͠ɺ࣮ߦதͷॲཧ͕׬ྃ͢Δ·Ͱ࣍ͷॲཧͷ։࢝
    ΛϒϩοΫ͢ΔҰൠతͰ௚ײతͳૢ࡞Ͱ͢ɻ͜ͷಉظॲཧͷΤϥʔϋϯυϦϯά͸ɺಉ
    ظॲཧΛtry/catchͰғ͏͜ͱʹΑͬͯߦ͍·͢ɻ
    try {
    // JSON.parseの例外処理は特に忘れがちなので注意してください
    const data = JSON.parse('invalid_json')
    } catch (err) {
    console.error(err)
    }
    try {
    const data = fs.readFileSync('invalid_path')
    } catch (err) {
    console.error(err)
    }
    fs.readFileSync΍thrownewError()΋try/
    catchΛ࢖ͬͯΤϥʔΛॲཧ͠·͢ɻಉظॲཧͷΤϥʔ͸
    ϋϯυϦϯά͕࿙Ε͍ͯΔͱϓϩηε͕Ϋϥογϡ͢Δͨ
    Ίɺे෼ʹ஫ҙ͍ͯͩ͘͠͞ɻ
    !
    36 / 53

    View Slide

  37. νΣοΫϙΠϯτ
    ‣ /PEFKT͸-54όʔδϣϯΛར༻͢Δ
    ‣ Ϟδϡʔϧͷར༻ͱ؅ཧํ๏Λཧղ͢Δ
    ‣ ඇಉظॲཧΛۦ࢖ͯ͠Πϕϯτϧʔϓͷఀࢭ࣌ؒΛ࠷খݶʹ཈͑Δ
    ‣ ίʔϧόοΫͱΠϕϯτۦಈͷσβΠϯΛཧղ͢Δ
    ‣ ίʔϧόοΫͱΠϕϯτۦಈͷΤϥʔϋϯυϦϯάํ๏Λཧղ͢Δ
    ‣ ಉظॲཧͷΤϥʔϋϯυϦϯάํ๏Λཧղ͢Δ
    ઃܭύλʔϯ ΤϥʔϋϯυϦϯά Ϋϥογϡ
    ඇಉظॲཧ
    $BMMCBDL if (err)
    &WFOU&NJUUFS emitter.on(‘error') ✔
    ಉظॲཧ try/catch ✔
    !
    37 / 53

    View Slide

  38. ϑϩʔ੍ޚ

    View Slide

  39. ϑϩʔ੍ޚ
    app.get(‘/upload', (req, res) => {
    // 1. データベースに問い合わせてユーザー情報を取得する非同期処理
    // 2. オブジェクトストレージにファイルをアップロードする非同期処理
    // 3. データベースにメタ情報を保存する非同期処理
    res.status(200).end(data)
    }
    8FC"1*ͷ։ൃͰ͸ԼهͷΑ͏ʹ௚ྻͷॲཧʢલͷॲཧ͕ऴ͔ྃͯ͠Β࣍ͷॲཧΛߦ͏ʣΛه
    ड़͢Δ͜ͱ͕΄ͱΜͲͰ͕͢ɺඇಉظॲཧͱ௚ྻॲཧͷ૬ੑ͸࠷ѱͰ͢ɻ͔͠͠ݱࡏͰ
    ͸௚ྻॲཧͷهड़Λվળ͢ΔݴޠϨϕϧͷ࢓༷͕උΘ͍ͬͯ·͢ɻ
    !
    39 / 53

    View Slide

  40. ϑϩʔ੍ޚֶशͷྲྀΕ
    ֶशॱ ઃܭύλʔϯ ޓ׵ੑ ϑϩʔ੍ޚ ετϦʔϜॲཧ هड़ྔ
    $BMMCBDL ✔
    &WFOU&NJUUFS ✔
    1SPNJTF ✔ ✔
    BTZODBXBJU ✔ ✔ ✔
    جૅͷσβΠϯύλʔϯʹΑΔϑϩʔ੍ޚΛɺΑΓ্Ґͷϑϩʔ੍ޚʹม׵͢Δ͜ͱͰֶशΛਐ
    Ί͍͖ͯ·͢ɻࠓճ͸தؒ૚Ͱ͋ΔPromiseΛεΩοϓͯ͠ɺ࠷ऴతͳண஍఺Ͱ͋Δasync/
    awaitΛղઆ͠·͢ɻ
    !
    40 / 53
    ֤ઃܭύλʔϯͷ্Ґޓ׵Ͱ͋Δasync/awaitΛղઆ͠·͢ɻ

    View Slide

  41. ίʔϧόοΫʹΑΔϑϩʔ੍ޚ
    ίʔϧόοΫΛ࢖ͬͨϑϩʔ੍ޚ͸༰қʹཧղͰ͖Δγϯϓϧͳ࢓૊ΈͰ͸͋Γ·͢
    ͕ɺॲཧͷ಺༰࣍ୈͰ͸ਂ͍ωετͱ࠶ىॲཧʹΑΓɺෳࡶ͕͞૿͠ՄಡੑͷѱԽͱه
    ड़ྔͷංେԽʹܨ͕Γ·͢ɻ
    // 再帰処理による非同期処理のループ
    const fs = require('fs')
    const write = (i) => {
    if (i === 100) return
    fs.appendFile('./data.txt', `${i},`, (err) => {
    write(++i)
    })
    }
    write(0)
    ϑΝΠϧ΁ͷॻ͖ࠐΈ͕׬ྃͨ͋͠ͱ࣍ͷॲཧΛ։࢝͢Δ
    ͱ͍͏௚ྻॲཧͰ͕͢ɺඇಉظॲཧͷͨΊϑΝΠϧॻ͖ࠐ
    Έ׬ྃͷίʔϧόοΫΛى఺ʹ࠶ؼॲཧ͍ͯ͠·͢ɻ
    !
    41 / 53

    View Slide

  42. ϑϩʔ੍ޚ›ඇಉظؔ਺

    View Slide

  43. BTZODBXBJU
    const fs = require('fs').promises
    const main = async () => {
    for (let i = 0; i < 100; i++) {
    await fs.appendFile('./data.txt', `${i},`)
    }
    }
    main()
    const fs = require('fs')
    const write = (i) => {
    if (i === 100) return
    fs.appendFile('./data.txt', `${i},`, (err) => {
    write(++i)
    })
    }
    write(0)
    ίʔϧόοΫͷ࠶ؼॲཧΛasync/awaitʹม׵͠·͢ɻasync/awaitʹΑͬͯίʔ
    υελΠϧ͸Ұൠతͳಉظॲཧʹ͍ۙߏ଄ʹมԽ͠·͢ɻͰ͕͢ඇಉظॲཧͷϝϦοτ͸
    ଛͳΘΕ͓ͯΒͣɺॲཧͷ࣮ߦத΋ଞͷॲཧʹϦιʔεΛׂΓ౰ͯΔ͜ͱ͕Ͱ͖·͢ɻ
    $BMMCBDL BTZODBXBJU
    const data = await func()ͷΑ͏ʹඇ
    ಉظॲཧͷฦΓ஋Λड͚औΔ͜ͱ΋Ͱ͖·͢ɻ
    !
    43 / 53

    View Slide

  44. BTZODBXBJU
    const fs = require('fs').promises
    const main = async () => {
    for (let i = 0; i < 100; i++) {
    await fs.appendFile('./data.txt', `${i},`)
    }
    }
    main()
    asyncfunctionએݴʹΑͬͯඇಉظؔ਺ʢ"TZOD'VOUJPOʣΛఆٛ͠·͢ʢ⁞ʣɻඇಉ
    ظؔ਺ͷ಺෦Ͱ͸awaitʹΑͬͯඇಉظॲཧͷ׬ྃΛ଴ػͰ͖·͢ʢ ʣɻ
    Promise͸4USVDUVSFEͳίʔϧόοΫͰ͢ɻ
    /PEFKTͷҰ෦ͷඪ४Ϟδϡʔϧ͸.promises
    Λ෇༩͢Δ͜ͱͰίʔϧόοΫͱಉ໊͡લͷ
    1SPNJTF"1*Λฦ͠·͢ʢ⁠ʣɻ
    ௨ৗͷίʔϧόοΫ"1*Ͱ͸awaitʹΑͬͯॲཧͷ׬ྃΛ଴ػͤ͞Δ͜ͱ͕Ͱ͖·ͤΜɻ
    awaitʹ౉͢ඇಉظॲཧ͸ಛఆͷϧʔϧʹैͬͨΦϒδΣΫτͰ͋Δඞཁ͕͋Γ·͢ɻ



    !
    44 / 53

    View Slide


  45. ԼهίʔϧόοΫύλʔϯͷ࠶ؼॲཧΛasync/awaitΛ࢖ͬͨॲཧʹม׵͍ͯͩ͘͠͞ɻ
    ԋश
    const fs = require('fs')
    const write = (i) => {
    if (i === 100) return
    fs.appendFile('./data.txt', `${i},`, (err) => {
    write(++i)
    })
    }
    write(0)
    ͜ͷࢿྉͷϦϯΫ https://speakerdeck.com/ajido/minimum-handson-nodejs
    ԋशϦϯΫ
    https://chouseisan.com/s?h=4a0d7eb9c38a440e9ad585abfbb16e79
    ‣ bit.ly/2XWSQQK
    εΫϦϓτϦϯΫ https://github.com/ajido/nodejs-handson
    !
    45 / 53

    View Slide

  46. Πϕϯτۦಈύλʔϯͷϑϩʔ੍ޚ
    try {
    for await (const keys of stream) {
    for (const key of keys) {
    console.log(key)
    }
    }
    } catch (err) {
    console.error(err)
    }
    Πϕϯτۦಈܕͷॲཧ΋forawaitߏจʹΑΓ
    "TZOD'VODUJPOͷϑϩʔ੍ޚԼʹ૊ΈࠐΉ͜
    ͱ͕Ͱ͖·͢ɻ
    const Redis = require('ioredis')
    const redis = new Redis()
    const stream = redis.scanStream({
    match: '*',
    count: 100
    })
    // 約100件のキーを読み込むごとに呼び出される
    stream.on('data', (keys) => {
    for (const key of keys) {
    console.log(key)
    }
    })
    // 全てのキーを走査した後に呼び出される
    stream.on('end', () => {
    console.log(‘end')
    })
    // 何かしらエラーが発生した時に呼び出される
    stream.on('error', (err) => {
    console.error(err)
    })
    ίʔϧόοΫ͕PromiseʹΑͬͯߏ଄Խ͞Ε͍ͯͨΑ͏
    ʹɺΠϕϯτۦಈܕͷॲཧ΋stream.ReadableʹΑͬͯ
    ߏ଄Խ͞Ε͍ͯΔඞཁ͕͋Γ·͢ɻ
    !
    46 / 53

    View Slide


  47. ԼهΠϕϯτۦಈύλʔϯͷίʔυΛforawaitΛ࢖ͬͨॲཧʹม׵͍ͯͩ͘͠͞ɻ
    ԋश
    const fs = require('fs')
    const rs = fs.createReadStream(__filename)
    rs.on('data', (data) => {
    console.log(data.toString())
    })
    rs.on('error', (err) => {
    console.error(err)
    })
    ͜ͷࢿྉͷϦϯΫ https://speakerdeck.com/ajido/minimum-handson-nodejs
    ԋशϦϯΫ
    https://chouseisan.com/s?h=4a0d7eb9c38a440e9ad585abfbb16e79
    ‣ bit.ly/2XWSQQK
    εΫϦϓτϦϯΫ https://github.com/ajido/nodejs-handson
    !
    47 / 53

    View Slide

  48. BTZODBXBJUͷΤϥʔϋϯυϦϯά
    "TZOD'VODUJPOͷ಺ଆͰ͸try/catchΛʢ⁞ʣɺ"TZOD'VODUJPOͷ֎ଆͰ
    ͸.catchΛ࢖ͬͯΤϥʔΛॲཧ͍ͯͩ͘͠͞ʢ ʣɻ
    const fs = require('fs').promises
    const main = async () => {
    for (let i = 0; i < 100; i++) {
    try {
    await fs.appendFile('./data.txt', `${i},`)
    } catch (err) {
    console.error(err)
    }
    }
    }
    main().catch((err) => {
    console.error(err)
    })


    "TZOD'VODUJPOͷ಺෦ͰΤϥʔ͕ൃੜ͢
    ΔͱɺҎ߱ͷॲཧ͸࣮ߦ͞Εͣ.catchʹ
    δϟϯϓ͠·͢ɻ
    ͨͩ͠"TZOD'VODUJPO಺෦ͷΤϥʔൃੜ
    ෦෼͕try/catchͰแ·Ε͍ͯΔ৔߹͸ɺ
    try/catchʹัଊ͞Ε.catchʹ͸ಧ͖·
    ͤΜɻ͜ͷ৔߹try/catchΛൈ͚ͨޙ΋
    "TZOD'VODUJPO಺ͷॲཧ͸ܧଓ͞Ε·͢ɻ
    !
    48 / 53

    View Slide

  49. BTZODBXBJUͷΑ͋͘Δࣦഊྫ
    ⁞awaitͷॻ͖๨Ε
     ෆཁͳPromiseͷར༻
    ⁠.catchͷॻ͖๨ΕʢΤϥʔϋϯυϦϯάͷهड़࿙Εʣ
    const fs = require('fs').promises
    const main = async () => {
    for (let i = 0; i < 100; i++) {
    const stat = fs.appendFile('./data.txt', `${i},`).then(() => {
    return fs.stat(‘./data.txt’)
    }) // await fs.appendFile('./data.txt', `${i},`)
    console.log(stat) // const stat = await fs.stat('./data.txt')
    }
    return Promise.resolve(‘done') // return 'done'
    }
    main().then((result) => console.log(result)) // .catch((err) => console.error(err))
    ⁞  


    !
    49 / 53

    View Slide

  50. BTZODBXBJUΛ࢖ͬͨแׅతͳΤϥʔϋϯυϦϯά
    BTZODBXBJU ݫີʹ͸1SPNJTF
    ͸try/catchͷ໾ׂΛ݉Ͷἧ͍͑ͯ·͢ɻԼهίʔυͰ͸
    "TZOD'VODUJPOͷ಺ଆͰൃੜ͢ΔಉظॲཧͷΤϥʔΛ.catchʹٵऩ͍ͤͯ͞·͢ɻॲཧΛ͢
    ΂ͯasync/await؀ڥԼʹ࣮૷͢Δ͜ͱͰɺඇಉظɾಉظॲཧΛ໰ΘͣɺแׅతʹΤϥʔΛॲཧ
    Ͱ͖·͢ɻ
    const main = async () => {
    JSON.parse('invalid_json')
    }
    main().catch((err) => {
    console.error(err)
    })
    // SyntaxError:
    // Unexpected token b in JSON at position 0
    // at JSON.parse ()
    try/catchͷهड़࿙ΕʹΑΔϓϩηεμ΢ϯΛ๷͗·͢ɻ͢΂ͯͷ
    έʔεʹ͓͍ͯasync/awaitΛར༻͢Δͱ͍͏ϧʔϧ͸Ұݟۃ୺
    ʹࢥ͑Δ͔΋͠Ε·ͤΜ͕ɺՄಡੑͷ໘Ͱ΋҆શੑͷ໘Ͱ΋͓͢͢Ί
    Ͱ͖Δ༏Εͨํ๏Ͱ͢ɻ
    !
    50 / 53

    View Slide

  51. νΣοΫϙΠϯτ
    ‣ BTZODBXBJUͷѻ͍ํΛཧղ͢Δ
    ‣ BTZODBXBJUͷΤϥʔϋϯυϦϯάํ๏Λཧղ͢Δ
    ‣ Մಡੑͱ҆શੑΛߟྀ͠ɺՄೳͳݶΓBTZODBXBJUϑΝʔετͷઃܭΛ৺ֻ͚Δ
    ઃܭύλʔϯ ΤϥʔϋϯυϦϯά Ϋϥογϡ
    ඇಉظॲཧ
    $BMMCBDL if (err)
    &WFOU&NJUUFS emitter.on(‘error') ✔
    BTZODBXBJU try/catch .catch()
    ಉظॲཧ try/catch BTZODBXBJU ✔
    !
    51 / 53

    View Slide

  52. جૅ Ԡ༻
    ‣ Πϯετʔϧ 5 ‣ ϑϩʔ੍ޚ 38
    ‣ Ϟδϡʔϧ؅ཧ 11 ‣ ඇಉظؔ਺ 42
    ‣ ಛ௃ 16 ‣ σόοά
    ‣ σβΠϯύλʔϯ 21 ‣ Ϟδϡʔϧͷ࡞੒
    ‣ ίʔϧόοΫ 23 ‣ ϓϩϑΝΠϦϯά
    ‣ Πϕϯτۦಈ 31 ‣ ϑϨʔϜϫʔΫͱπʔϧ
    ‣ ಉظॲཧ 35

    View Slide

  53. ௕͓࣌ؒർΕ༷Ͱͨ͠ɻ
    Photo by Paul Hanaoka on Unsplash

    View Slide