Sunday, August 17, 2014

node.js q promise

node.jsでpromise(deffered)を使いたかったので現状どうなってるのか簡単に調べた。
まず、本家のPromiseだけど安定板のv0.10.30ではまだサポートされていない。仕方ないのでlatestv0.11.13を使って試してみる。

node.js Promise

サンプルコード。
function promiseA() {
    return new Promise(function(onFulfilled, onRejected) {
        setTimeout(function() {
            console.log('I execute first.');
            onFulfilled();
        }, 1000);
    });
}

function promiseB() {
    return new Promise(function(onFulfilled, onRejected) {
        setTimeout(function() {
            console.log('I execute second.');
            onFulfilled();
        }, 5000);
    });
}

function promiseC() {
    return new Promise(function(onFulfilled, onRejected) {
        setTimeout(function() {
            console.log('I execute third.');
            onFulfilled();
        }, 5000);
    });
}


promiseA().then(promiseB).then(promiseC);
// ダメ. 関数を実行してしまい、promiseBとpromiseCが同時に動く.
//promiseA().then(promiseB()).then(promiseC());
こんな感じか。
最初はnew Promise(..)で取得したオブジェクトを直接thenに指定してしまい、promiseB, promiseCが同時に実行されてはまる。
お馬鹿な例。
var promiseA = new Promise(function(fulfill, reject) {
    setTimeout(function(){ console.log('first.') },1000);
});
var promiseB = new Promise(function(fulfill, reject) {
    setTimeout(function(){ console.log('second.') },1000);
});
var promiseC = new Promise(function(fulfill, reject) {
    setTimeout(function(){ console.log('third.') },1000);
});

promiseA.then(promiseB).then(promiseC);
newした瞬間に処理実行されちゃってるからな。このnew、地味にこういう誤解を招くと思うんだけど…。

Q

node.jsの現バージョンであるv0.10.30はPromiseをまだ実装していない。ぐぐったらQがデファクトっぽい扱いだったのでこちらで同様の事を試みる。

サンプルコード
var Q = require('q');

function one() {
    var deffered = Q.defer();

    setTimeout(function() {
        console.log('execute one.');
        deffered.resolve();
    }, 1000);

    return deffered.promise;
}

function two() {
    var deffered = Q.defer();

    setTimeout(function() {
        console.log('execute two.');
        deffered.resolve();
    }, 1000);

    return deffered.promise;
}

function three() {
    var deffered = Q.defer();

    setTimeout(function() {
        console.log('execute three.');
        deffered.resolve();
    }, 1000);

    return deffered.promise;
}

one().then(two).then(three).done();
関数内でdefferedを作り、返り値をdeffered.promise、処理完了をdeffered.resolve()で伝えてあげればいいみたい。こっちのほうが凄いしっくりくる。node.js/Promisethenable使えば似たような感じになりそうだけど、いちいち自前でnewを書くのがちょっと面倒に感じた。

No comments:

Post a Comment