みやちゃ
今回は、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()
まとめ
いかがでしたでしょうか?
今回は、コールバック地獄の解決策をご紹介しました!
みやちゃ
ここまでご覧いただきありがとうございます!