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

NodeJS と generator

Stream をやっとまともに触り始めたついでに generator も触ってみた。node は v0.11.13 です。

Generators - JavaScript | MDN

*a2z は a から z までを順に yield に指定しているので、g.next() を呼び出すたびに a からインクリメントされたアルファベットが返される。

function* a2z() {
    var c = 97;

    while (c <= 'z'.charCodeAt(0)) {
        yield String.fromCharCode(c++);
    }

    return;
}

var g = a2z();
process.stdout.write(g.next().value);
process.stdout.write(g.next().value);
process.stdout.write(g.next().value);

// node --harmony a2z.js
// abc

generator と同じく ES6 の for...of に generator を渡すと最後まで繰り返してくれる。

for...of - JavaScript | MDN

function* a2z() {
    var c = 97;

    while (c <= 'z'.charCodeAt(0)) {
        yield String.fromCharCode(c++);
    }

    return;
}

for (var a of a2z()) {
    process.stdout.write(g.next().value);
}

// node --harmony a2z.js
// abcdefghijklmnopqrstuvwxyz

最後に Stream の勉強も兼ねて stream-handbook のサンプルをジェネレータで書いてみた。100 ms ごとに a から z までが出力される。

function* a2z() {
    var c = 97;

    while (c <= 'z'.charCodeAt(0)) {
        yield String.fromCharCode(c++);
    }

    return;
}

var Readable = require('stream').Readable;
var rs = Readable();
var g = a2z();

rs._read = function () {
    var that = this;
    setTimeout(function () {
        that.push(g.next().value);
    }, 100);
};

rs.pipe(process.stdout);

// node --harmony a2z.js
// abcdefghijklmnopqrstuvwxyz

ちなみに generator の定義方法は function* generatorfunction *generator (アスタリクスの位置が違う)を見かけるが MDN では function* と記載されているのでここではそちらで統一している。