Javascript Node.js React プログラミング

非同期処理 コールバック地獄 解決策【Node.js 入門#3】

 

みやちゃ

 

皆さんこんにちは、みやちゃです!

物理とプログラミングについて解説しています!

こちらの記事で、Railsのアプリケーション開発からRspecのテスト、herokuにデプロイまで解説しています!

今回は、Node.js入門の第三弾です!

コールバック地獄の解決策をご紹介します。

今回は
  • コールバック地獄の解決策
この記事を読むと

コールバック地獄の解決策を理解することができます!

目次

コールバック地獄とは

非同期処理で入出力処理を連続で行う際、何も考えずにプログラムを書いて、非常に読みにくいコードが出来上がることを言います。

例として以下のコードを見てください。

const fs = require('fs')
fs.readFile('a.txt', 'utf-8', function (err, data) {
  console.log('a.txtを読みました', data)
  fs.readFile('b.txt', 'utf-8', function (err, data) {
    console.log('b.txtを読みました', data)
    fs.readFile('c.txt', 'utf-8', function (err, data) {
      console.log('c.txtを読みました', data)
    })
  })
})

上記のコードでは、「a.txt」、「b.txt」、「c.txt」の3つのファイルを連続で読み込んでいます。

何も考えずに、これら3つのファイルを読み込もうとすると、上記のコードのように、3回コールバック関数をネストさせ、かなり読みづらいコードとなっています。

これがもっと多くのファイルを読み込む必要があるとなると、、

かなり気味が悪いです。

これが「コールバック地獄」と呼ばれるものです。

解決策1:Promise

Promiseでは、Promiseオブジェクトを返しておいて、実行処理が完了した時点で、実際の値が得られるようにするというものです。

以下のコードを見てください。

const fs = require('fs')

function readFile_pr (fname) {
  return new Promise((resolve) => {
    fs.readFile(fname, 'utf-8', (err, s) => {
      resolve(s)
    })
  })
}
readFile_pr('a.txt')
.then((text) => {
  console.log('a.txtを読みました', text)
  return readFile_pr('b.txt')
})
.then((text) => {
  console.log('b.txtを読みました', text)
  return readFile_pr('c.txt')
})
.then((text) => {
  console.log('c.txtを読みました', text)
})

解決策2:Generator

Generatorは、Generator関数を定義し、その関数の中で、yieldが出てくるまでの部分が実行され、再び、Generator関数が呼び出されると、その次のyieldまでの部分が実行されるというものです。

つまり、関数を途中で中断し、yieldで非同期処理が終わるのを待って、終わり次第、続きの関数を実行するというものです。

以下のコードを見てください。

const fs = require('fs')

function read_gfn (g, fname) {
  fs.readFile(fname, 'utf-8', (err, data) => {
    g.next(data)
  })
}
const g = (function * () {
  const a = yield read_gfn(g, 'a.txt')
  console.log(a)
  const b = yield read_gfn(g, 'b.txt')
  console.log(b)
  const c = yield read_gfn(g, 'c.txt')
  console.log(c)
})()
g.next()

解決策3:async/await

async/awaitは、PromiseやGeneratorを使ったプログラムをより簡潔に記述することができます。

以下のコードを見てください。

const fs = require('fs')

function readFileEx (fname) {
  return new Promise((resolve, reject) => {
    fs.readFile(fname, 'utf-8', (err, data) => {
      resolve(data)
    })
  })
}
async function readAll () {
  const a = await readFileEx('a.txt')
  console.log(a)
  const b = await readFileEx('b.txt')
  console.log(b)
  const c = await readFileEx('c.txt')
  console.log(c)
}

readAll()

まとめ

いかがでしたでしょうか?

今回は、コールバック地獄の解決策をご紹介しました!

 

みやちゃ

 

ここまでご覧いただきありがとうございます!

© 2024 とあるエンジニアの備忘録ブログ Powered by AFFINGER5