ユーザ用ツール

サイト用ツール


nodejs

文書の過去の版を表示しています。


node.js

node.jsはノンブロッキングI/Oとイベント駆動が特徴のJavaScript実行環境。イベントループ型のサーバを簡単に実装できる。Chromeブラウザと同じV8エンジンが使用されている。

バージョンとES feature

ブラウザと違って互換性を気にする必要はないので

node v4

* デフォルト引数、分割代入、import以外のES2015機能が使えます。

node v6

* import以外のES2015機能が使えます。

callbackに関するtips

callbackの第一引数はerrにする

絶対にエラーの発生しない処理だとしてもcallbackの第一引数はエラーが渡される想定のコードにすること。第一引数にnullを渡してcallbackを呼べし。

node, npmの多くのライブラリは第一引数でエラーを受け取る事を前提にしているので、こうすることで各種ライブラリ、モジュールとスムーズに連携できるようになる。

// これはだめ
function asyncFunc(callback) {
   setImmediate(function() {
      callback(true);
   });
}
// OK
function asyncFunc(callback) {
   setImmediate(function() {
      callback(null, true);
   });
}

非同期処理には必ずcallbackを

呼び出し元に結果を通知する必要のない非同期処理でも必ずcallbackを付ける(PromiseかEvent駆動ならcallbackなし可)

bad

function writeLogToDB(code, content) {
   // 失敗しても良い処理なので、呼び出しもとにエラーを通知しなくてもいい (← ダメです。だいたい後で通知したくなります)
   db.Log.insert({_id: code, content: content}, function(err) {
      err && mainLogger.error(err);
   });
}

good

function writeLogToDB(code, content, callback) {
   // callbackが渡されてなければデフォルトの処理を入れる
   if (!callback) callback = function(err) {
      err && mainLogger.error(err);   
   }
 
   db.Log.insert({_id: code, content: content}, function(err) {
      callback(err);
   });
}

callbackを2度呼ばない

function someAsyncFunc(callback) {
   // 途中省略...
   
   try {
       callback();
   } catch (e)
       callback(e);
   }
}

try側のcallback中に例外が発生するとcatch側のcallbackが呼ばれるので2回呼ばれてしまう。これによってデータ2重書き込み等の重大な問題が発生する恐れがあります。

require

require時に処理を走らせない

requireされるファイルは関数やクラスの定義のみにする。読み込んだだけでファイルの書き込み読み込み、サーバの起動、DB接続その他の処理を行ってはいけない。

Good

// hoge.js
var hoge = module.exports;
 
hoge.init = function() {
  // 何か初期化処理
}
 
 
// main.js
var hoge = require("./hoge");
hoge.init();              // 初期化処理の実行はrequireしたファイルで行う

Bad

// hoge.js
var hoge = module.exports;
 
hoge.init = function() {
  // 何か初期化処理
}
 
hoge.init();  
 
 
// main.js
require("./hoge");        // requireしただけでinitされてしまう

requireされるだけで何らかの処理が走るようにすると、起動時に予期せぬタイミングでinitが実行されたり、テストコードでinitが不要なのに呼ばれてしまったりする問題が発生します。

HTML5 の Server-Sent Events を実装してみる

node.jsでServer-Sent Eventsを試す - nullpo.printStackTrace();

サーバ側を node.js で実装してみる。

generator.js

// EventEmitterを取得
var events = require("events");
var emitter = new events.EventEmitter();
 
// EventEmitterを拡張
emitter.id = 0;
emitter.data = "";
emitter.start = function() {
    var chars = "node.js";
    var self = this;
    setInterval(function() {
        var pos = Math.floor(Math.random() * chars.length * 2); 
        if (pos < chars.length) {
            self.id++;
            self.data = chars.charAt(pos);
            // generatedイベントとして登録されたリスナを呼び出す
            self.emit("generated", self.id, self.data);  
        }
    }, 1000);
};
 
// module.exportsに設定されたオブジェクトがrequireの戻り値となる。
module.exports = emitter; 

server.js

var http = require("http")
http.createServer(handler).listen(8124);
 
var generator = require("./generator")
generator.start();
 
function handler(req, res) {
 
    function response(id, data) {
        generator.removeListener("generated", arguments.callee);
 
        res.writeHead(200, {
            "Content-type": "text/event-stream"
        });
        res.write("id:" + id + "\n");
        res.write("data:" + data + "\n");
        res.write("retry: 1000");
        res.end();
 
    }
    generator.on("generated", response);
}

クライアント側のJavaScript

var source = new EventSource(url);
source.onmessage = function(event) {
  // データ受信時の処理を書く
  // event.data でサーバから送られてきたデータを取得できる
}
nodejs.1475481637.txt.gz · 最終更新: 2016/10/03 08:00 by nullpon