Node.js:async.forEachSeries

昨日のプログラム、うまくいったので書く。

結果から書くと、アクションの中で callback を呼び出させばいいようだ。プログラムはこんなふうになった。

var http = require('http');
var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var async = require('async');

var host = "http://localhost:8888/";

var action = {
  new: getNewItem,
  delete: deleteItem
}

function replicate(host) {
  var req = http.get(host + "recent.json", function(res) {
    var body = "";
    res.setEncoding('utf8');
    res.on('data', function(chunk) {
      body += chunk;
    });
    res.on('end', function(res) {
      var items = JSON.parse(body);
      async.forEachSeries(items, function(item, callback) {
        action[item.action](item, callback);
      });
    });
  }).on('error', function(err) {
    colsole.log("Error: " + err.message);
  });
}

function getNewItem(item, callback) {
  console.log("New item: " + item.path);
  var filepath = "./storage/" + item.path;
  var dir = path.dirname(filepath);
  mkdirp(dir, function(e) {
    if (e) {
      console.log(e.message);
    } else {
      var itemUrl = host + item.path;
      var ws = fs.createWriteStream(filepath);
      var req = http.get(itemUrl, function(res) {
        res.pipe(ws);
        res.on('end', function() {
          ws.close();
          console.log("New: " + item.path + "...done.");
          callback(null);
        });
      });
    }
  });
}

function deleteItem(item, callback) {
  console.log("Delete item: " + item.path);
  var filepath = "./storage/" + item.path;
  fs.unlink(filepath, function(e) {});
  console.log("Delete: " + item.path + "...done.");
  callback(null);
}

replicate(host);

アクションの最後、特に getNewItem ではネストの一番深いところで callback を呼び出している。これが次のアクションを呼び出すことになっているわけだ。
実行結果。

^o^ > node replicate.js
New item: Penguins.jpg
New: Penguins.jpg...done.
New item: data/Desert.jpg
New: data/Desert.jpg...done.
Delete item: Penguins.jpg
Delete: Penguins.jpg...done.

ちゃんと指示通りの順番で実行されている。

^o^ > tree /F storage
フォルダー パスの一覧:  ボリューム OS
ボリューム シリアル番号は FE2A-F7C6 です
C:\USERS\TAKATOH\DOCUMENTS\W\REPLICATE\STORAGE
└─data
        Desert.jpg

Penguins.jpg は削除されて残っていないのがわかる。