読者です 読者をやめる 読者になる 読者になる

S.F. Page

Programming,Music,etc...

Wordpress DBからカテゴリのディレクトリツリーを作る(2)

うまく書けたような

昨日の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()を遅延させることで、終了検知ができるようになった。 非同期処理の処理フローはやっぱり同期処理と違った考え方をしないといけないので、慣れるまでは難しいね。慣れても難しいかもしれないけども。