nodejs
文書の過去の版を表示しています。
目次
node.js
node.jsはノンブロッキングI/Oとイベント駆動が特徴のJavaScript実行環境。イベントループ型のサーバを簡単に実装できる。Chromeブラウザと同じV8エンジンが使用されている。
callbackに関するtips
callbackの第一引数はerrにする
絶対にエラーの発生しない処理だとしても第一引数はエラーにする。node, npmの多くのライブラリは第一引数がerrである事を前提にしている。
// これはだめ 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.1475462867.txt.gz · 最終更新: 2016/10/03 02:47 by nullpon