ペチパーノート

WEB開発系Tipsブログです。

Javascript 非同期処理の歴史

コールバック地獄から抜け出す方法

  • ES2015のPromiseを使った方法
  • ES2015のGeneratorを使った方法
  • ES2017のasync awaitを使った方法

サンプルソース

/**
 * Promiseを使った方法
 */
const fs = require('fs');

// Promiseを返す関数を定義
function readFile_pr (fname) {
  return new Promise((resolve) => {
    // ここに非同期処理を書く
    fs.readFile(fname, 'utf-8', (err, s) => {
      // 成功した時に返したい値(s)をresolveで返す
      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)
})


----------------------------------------------

/**
 * Generatorを使った方法
 */
const fs = require('fs')

// 非同期処理の完了を待って関数の続きを呼ぶ関数
function read_gfn (g, fname) {
  fs.readFile(fname, 'utf-8', (err, data) => {
    g.next(data)
  })
}

// Generator関数の定義
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 a = yield read_gfn(g, 'c.txt')
  console.log(c)
})()
g.next()

----------------------------------------------

/**
 * ES2017のasync/awaitを使った方法
 */
 const fs = require('fs')

 // Promiseで非同期ファイルを読み込む関数を定義
function readFileEx (fname) {
  return new Promise((resolve, reject) => {
  fs.readFile(fname, 'utf-8', (err, data) => {
    resolve(data)
    })
  })
}


// すべてのファイルを逐次読み込むasync関数を定義
// asyncを付けた関数の中ではawaitを使える様になる
async function readAll () {
  // Promiseを返す関数にawaitをつけると、resolve()で返された値が返ってくるように見える
  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)
}

readAall()