Node.jsの対話的実行環境(REPL)
コンソールでnodeを触る事が可能。
どういった場面で使用するか? -> 正規表現の確認等
- REPL小技
REPLを利用している時の、_という記号は直前の実行結果を表す。
Node.jsは非同期プログラミングを基本とするため、単純に上から順にプログ ラムを書いていっても、予想どうりには動かない。 解決策は二つ。
-
コールバック
解決策として一般的なのが、コールバックを使うこと。 非同期処理の場合、終わった時に呼び出すメソッドを処理として引数に渡すことができる。 関数を引数に取り、処理が終わったら呼び出される関数のことをコールバックと呼ぶ。
// httpモジュールを読み込み、httpという同名の変数に格納しています。
// requireはモジュール読み込みのためのグローバルモジュールです。
// requireを記述する時は慣例として、ファイルの先頭に記述することが多いです。
var http = require('http');
// httpモジュールのメソッドである、createServerを呼出し、
// サーバーを作成します。
var server = http.createServer(function(req, res) {
// レスポンスに文字列を渡す。
res.end("Hello NodeJS");
});
// ポート番号3000番で受け付けるサーバーを起動する。
server.listen(3000, function() {
// 起動したことを表すメッセージを追加。
console.log('Server started, listening on : 3000');
});
非同期処理のlistenでもサーバーが起動した時に3000番で待ち受け可能。
-
Event Emitter
イベントが発生する度に処理を呼び出すイベント駆動と呼ばれるNode.jsの特徴的なモデルで、こっちのほうがjQuery等の記述と似ているため馴染みやすいかもしれない。
var http = require('http');
var server = http.createServer(function(req, res) {
res.end("Hello JSCafe");
});
// listeningイベントを受け取り、表示する。
server.on('listening', function(){
console.log('Server started, listening on : 3000');
});
server.listen(3000);
exports
というオブジェクトのプロパティに対して関数や値を渡せば、require
した側で利用することができます。
exports
もmodule.exports
もどちらも変わらないが、module.exports
の方が少しだけ柔軟で、require
を呼び出した時の戻り値をモジュールではなく、関数や文字列、配列などの任意のオブジェクトの型にすることができる。
module.exports = 'Hello nodejs';
var msg = require('./module');
console.log(module.msg);
指定されたURLのページをコールバックでとってくるmodule
var http = require('http');
var Crawler = {
request : function(url, callback) {
http.get(url, function(res){
res.setEncoding('utf-8');
var buffer = '';
res.on('readable', function() {
buffer += res.read();
});
res.on('end', function() {
// コールバックを呼び出している部分。
// レスポンスが全て返ってきたのでコールバックを呼び出して
// 内容を第二引数に入れている
callback(null, buffer);
});
res.on('error', function(e) {
// エラーが発生したらエラーメッセージを受け取り、コールバックの
// 第一引数にエラーを入れて返します。
// 慣例的にエラーを返す事があるメソッドの場合、コールバックの第一引数をエラーにすることが多い
console.log('Got error: ' + e.message);
callback(e, buffer);
});
});
}
};
module.exports = Crawler;
try ~ catch の代わりに error イベントを登録。
次に、spider.jsを使用する
var crawler = require('./spider');
// コールバック呼び出し
crawler.request('http://atnd.org/events/37045', function(e, res) {
if (e) { console.log(e); }
console.log(res);
});
var http = require('http');
var emitter = require('events').EventEmitter;
var util = require('util');
function Crawler() {
emitter.call(this);
}
// event emitterを継承
// util.inherits(constructor, superConstructor)
util.inherits(Crawler, emitter);
Crawler.prototype.request = function(url) {
var self = this;
http.get(url, function(res) {
var buffer = '';
res.on('readable', function(){
buffer += res.read();
});
res.on('end', function() {
// 読み込みが終わったこととデータを通知
self.emit('end', buffer);
});
res.on('error', function(e) {
// エラーが発生したらその事を通知
self.emit('error', e);
});
});
return self;
};
module.exports = Crawler;
spider_emitter.jsを使用する
var Crawler = require('./spider_emitter');
var crawler = new Crawler();
crawler.request('http://atnd.org/events/37045');
crawler.on('end', function(page) {
console.log(page);
});
crawler.on('error', function(e) {
console.log(e);
});
結果は同じになる。
最初の記述との違い…
- request関数に渡していたコールバックの引数がない。
- EventEmitterを継承し、self.emitでイベントを発行。 仕様する側もon('end')でイベントを補足
イベントを発行するのが… emmit イベントを受信するのが… on
-
callback
分かりやすく手軽に使える 他の処理と重なると、コールバックが連続し、地獄になる
-
event emmiter
使う側はシンプルに書く事が出来る。 モジュール側は書くのが面倒だが、コードのモジュール性が高まる。
-
npm initで初期化 自分でモジュールを作成する際など、initで初期化する
-
npm searchで検索
$npm search pdf
で検索すると色んなモジュールが出てくるので、詳細を調べる際には、$ npm info node-pdf
で詳細情報を得る。 -
npm installでインストール 他の人が既に作成しているものを使用するにはnpm install
-
npm install -g でグローバルモジュールとしてインストール
- コールバックは単なるメソッド呼び出し。
function(arg0, arg1, …, option, callback) { }
- コールバック関数の第一引数はエラーオブジェクトにする
callback(err, arg0, arg1, ...){
if(err){
}
}
なんらかの応答が終わったら(完了用のイベントを受け取ったら)、そのメソッドを実行する(返す)だけの仕組み。