うまく書けたような
昨日のWordpressカテゴリを元にディレクトリを作成する処理の続き。非同期処理のためにMySQL接続をうまくクローズできない問題はコードを見直した結果、うまく解決できたような気がする。
var fs = require('fs');
var zlib = require('zlib');
var Q = require('q');
var dbj = fs.readFileSync('dbinfo.json', 'utf-8');
var dbinfo = JSON.parse(dbj);
var home_dir = './blog/';
var nfs = require('node-fs');
var mysql = require('mysql');
var TABLE = 'wp_posts';
//mysqlクライアント作成
var mySQLConn = mysql.createConnection({
user: dbinfo.user,
password: dbinfo.password,
database: dbinfo.db
});
// mysql.mySQLQuery メソッドをプロミスを返すバージョンに変換
var mySQLQuery = Q.nbind(mySQLConn.query, mySQLConn);
var qparent = 'select * from wp_terms inner join wp_term_taxonomy on wp_terms.term_id = wp_term_taxonomy.term_id where wp_term_taxonomy.taxonomy = "category" and wp_term_taxonomy.parent = ';
function create_category_dir(data) {
var qp = qparent + data.id;
// 終了検知のためのPromise
var defer = Q.defer();
var records = null;
// 子カテゴリ処理関数
function create_child_dir() {
var tasks = [];
for (var i = 0; i < records.length; ++i) {
var record = records[i];
var d = { id: record.term_id, name: record.name, slug: record.slug, childs: [], dir: data.dir + '/' + decodeURI(record.slug) };
// 子カテゴリを処理するための再帰呼び出し
var pr = create_category_dir(d);
// 子処理を完了検知するため配列に保存
tasks.push(pr);
data.childs.push(d);
}
if (!tasks.length) {
// リーフ(葉であれば)終了
defer.resolve();
} else {
// でなければ子の処理がすべて完了するまで終了を遅延
Q.all(tasks).then(defer.resolve.bind(defer));
}
}
// クエリする
mySQLQuery(qp).then(
function (result) {
// MYSQLへのクエリ成功
console.log('mySQLQuery クエリ成功');
records = result[0];
// ディレクトリ作成の処理Promiseを返す
return Q.nfcall(nfs.mkdir, data.dir, true);
}, function (err) {
// MYSQLへのクエリ失敗
console.log(err);
defer.reject(err);
}
).then(
// ディレクトリ作成処理が成功
function () {
console.log(data.dir);
// 子カテゴリのディレクトリを作成する
create_child_dir();
},
// ディレクトリ作成処理が失敗
function (err) {
if (err.code === 'EEXIST') {
// ディレクトリが存在しているのなら処理を続ける
console.log(data.dir);
create_child_dir();
} else {
// それ以外であれば処理を中断する
defer.reject(err);
}
}
);
return defer.promise;
}
var category = { id: 0, name : 'category', slug: 'category' , childs : [], dir : home_dir + 'category' };
create_category_dir(category)
.catch(function (err) {
// ディレクトリ作成処理失敗
console.log(err);
})
.done(function () {
// ディレクトリ作成処理完了
console.log('create_category_dir() done.');
// カテゴリーデータをJSON化して表示
console.log(JSON.stringify(category));
// MYSQL接続の終了
mySQLConn.end();
});
Defferedをうまく使って処理終了までresolve()を遅延させることで、終了検知ができるようになった。
非同期処理の処理フローはやっぱり同期処理と違った考え方をしないといけないので、慣れるまでは難しいね。慣れても難しいかもしれないけども。