==============
$ sudo yum install -y git openssl-devel gcc-c++ make lua-devel.x86_64 ncurses-devel
$ sudo yum install mercurial
$ cd /usr/local/src
$ sudo hg clone -r 29e57603bf6f3a2e3c178a63d332ed4d2eccfa82 https://vim.googlecode.com/hg/ vim7.3.1314
$ cd vim7.3.1314
$ sudo ./configure --enable-multibyte --with-features=huge --disable-selinux --prefix=/usr/local --enable-luainterp=yes --with-lua-prefix=/usr
$ sudo make && sudo make install
$ cd ~
$ git clone https://github.com/2tom/docs.git
$ mv docs/vimrc ~/.vimrc
$ vim
$ git clone git://github.com/creationix/nvm.git .nvm
$ cd .nvm
$ git checkout v0.24.0
$ cd ../
$ . .nvm/nvm.sh
$ nvm install v0.12.1
$ nvm use v0.12.1
$ npm install -g yo grunt-cli gulp bower
setTimeout(function() {
console.log('Timeout');
}, 1000);
console.log('Waiting');
var http = require('http');
http.createServer(function (req, res){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('Hello World\n');
}).listen(1337, '192.168.57.31');
console.log('Server running');
var http = require('http');
http.createServer(function (req, res){
var num = parseInt(req.url.slice(1));
if (isNaN(num)) {
res.end();
return;
}
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('fib('+num+') = ' + fib(num));
}).listen(1337, '192.168.57.31');
console.log('running');
function fib(n){
if (n === 0 || n === 1) return n;
return fib(n - 1) + fib(n - 2);
}
"use strict";
var count = 0;
module.exports = {
say:function(name){
count++;
console.log('Hello ' + name);
},
getCount:function(){
return count;
},
resetCount:function(){
count = 0;
}
}
$ node
> var hello = require('./hello');
undefined
> hello
{ say: [Function], getCount: [Function], resetCount: [Function] }
> hello.say('a');
Hello a
undefined
> hello.say('a');
Hello a
undefined
> hello.getCount();
2
$ node
> require.resolve('./hello');
'/home/vagrant/hello.js'
> require.resolve('http');
'http'
- node.js の http.createServer()は、APIに登録するコールバック関数はrequestイベント発生時に実行される
- javascriptで利用しているイベントはECMA-262では定義されておらず、W3CのDOM Class2 において定義されている
- node.jsでイベント自体を定義して、任意のタイミングで発生させ、そのイベントに応じた処理をする場合、処理の流れは以下のとおり
- イベントを発生するオブジェクトを作成する
- イベント発生時の処理関数(リスナ)を作成する
- イベントを定義する
- 任意のタイミングでイベントを発生させる
// オブジェクトの作成
var events = require('events');
var emitter = new events.EventEmitter();
// リスナの作成
var sampleListener = function(arg1){
console.log(arg1);
}
// リスナをイベントに紐付け
emitter.on('occur', sampleListener);
or
// イベント発生
emitter.emit('occur', 'occured');
// 一度限りのイベント
emitter.once('occur', ')
- EventEmitterオブジェクトには複数のリスナを登録可能
- デフォルトは10個以上のリスナ登録で警告(登録は実行できている)
- setMaxListeners()を利用すると数量変更可能(0 で無制限)
- emitter.listeners(event)で登録済みリスナを確認可能
- removeListener()でリスナ削除(全て消す場合はremoveAllListeners())
- process.on()でシグナルの受信が可能
process.on('SIGTERM', function(){
//終了処理
});
- whileで実装されている
- setTimout()のコールバック実行
- process.nextTick()のコールバック実行
- I/Oイベント発生
- I/Oイベントのコールバック実行
- process.nextTick()のコールバック実行
var http = require('http');
var server = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello');
});
server.listen(1337);
while(true); //このエントリにより、process.nextTick()で実行された
//初期化が完了せず、I/Oイベントであるrequestが飛んできても
// I/Oイベントが実施されない
- events.EventEmiiterでイベントを発生させる場合、下記問題が発生する場合がある
var events = require('events');
var util = require('util');
function SyncEmitter(){
this.emit('bar');
}
util.inherits(SyncEmitter, events.EventEmitter);
var foo = new SyncEmitter;
// new の時点でevent bar がemitされており、
// 下記リスナが実行されない。
foo.on('bar', function(){
console.log('bar emitted');
});
- 上記のようなケースに対応する場合は、process.nextTick()を使って リスナの登録処理後に非同期イベントが発生するようにする
var events = require('events');
var util = require('util');
function AsyncEmitter(){
var self = this;
process.nextTick(function(){
self.emit('bar');
});
}
util.inherits(AsyncEmitter, events.EventEmitter);
var foo = new AsyncEmitter();
// ここで正常にリスナが呼ばれる
foo.on('bar', function(){
console.log('bar event emitted');
});
- コールバックの実行もprocess.nextTick()で非同期に呼び出すことが可能
- 下記ケースでは、コールバックを同期的に実行しようとしてエラーになります
var events = require('events');
var util = require('util');
function SyncCB(cb){
if(cb)cb();
}
util.inherits(SyncCB, events.EventEmitter);
SyncCB.prototype.setbaz = function(arg){
this.baz =arg;
}
//コールバック中にオブジェクトメソッドfoo.setbaz()を実行していますが、
//変数fooにオブジェクトが代入される前であるため、undefinedのエラーが発生
var foo = new SyncCB(function(){
foo.setbaz('bar');
console.log(foo.baz);
});
上記ケースの解決方法として、process.nextTick()を使って非同期にコールバックを実行する
var events = require('events');
var util = require('util');
function AsyncCB(cb){
if(cb){
process.nextTick(function() {
cb();
});
}
}
util.inherits(AsyncCB, events.EventEmitter);
AsyncCB.prototype.setbaz = function(arg){
this.baz = arg;
}
var foo = new AsyncCB(function(){
foo.setbaz('bar');
console.log(foo.baz);
});
- ストリームはNodeにおいて様々なオブジェクト内で、データの流れを扱う際に利用される抽象的なインタフェース
- ストリームにおいて、入出力データはバッファ単位でストリーム上を流れている(チャンク)
- ストリームはすべてのEventEmmiterのインスタンスとなっており、状態変更がイベントによって通知される
-
データ読み込みを司る
-
入力ストリームのイベント
//data
- 読み込み開始でイベント発生
- リスナ関数にはBufferオブジェクトもしくは、ストリームオブジェクトがsetEncoding(encoding)メソッドでエンコード指定されていれば文字列が渡される
- setEncoding()にはutf8, ascii, base64を指定可能(デフォルトはutf8)
- dataイベントが発生しなくなるとendが生成
//end
- dataイベントが発生しなくなった際に生成される
//close
- ファイル記述子が閉じられた段階で生成される
//error
- 読み込み中にエラーが発生した場合に生成され、リスナに例外オブジェクトが渡される
- errorイベントリスナが登録されていない場合は uncaughtExceptionが発生
- メソッド
//destroy()
- データ読み込み処理を破棄する
- destory発行以降はイベントを生成せず、ファイル記述子は閉じられる
//pause()
- dataイベント発生を中断
- 主に入力データを出力ストリームに出力する際に利用
//resumre()
- dataイベントを再開
- 主に入力データを出力ストリームに出力する際に利用
//pipe(destination, [options])
- 出力ストリームに入力ストリームを接続
- destination = 出力ストリーム
- 入力ストリームの読み込みが完了した後、出力ストリームを閉じない場合false指定(デフォルトはtrue)
-
プロパティ
-
readableプロパティを確認することで読み込みの可否が判断できる
-
sample
$ cat instream.js
var path = require('path');
fs = require('fs');
var filePath = path.join(__dirname, 'a.txt');
var readStream = fs.createReadStream(filePath);
readStream.setEncoding('utf8');
readStream.on('data', function(data){
console.log(data);
});
readStream.on('end', function(){
console.log('end');
});
readStream.on('error', function(err){
console.log('error occured');
console.log(err);
});
- データ書き込みを司る
- 出力ストリームのイベント
//drain
- dataイベントが発生しなくなるとendが生成
//error
- dataイベントが発生しなくなった際に生成される
//close
- ファイル記述子が閉じられた段階で生成される
//pipe
- 読み込み中にエラーが発生した場合に生成され、リスナに例外オブジェクトが渡される
- errorイベントリスナが登録されていない場合は uncaughtExceptionが発生
- メソッド
//write()
- データ書き込み
- write()にはBufferを渡せる
- write(string, [encoding],[fd]) という形で文字列を書き込み可能
- fdを使用するとUNIXストリームでのみのサポート
- write()は出力対象のデータがカーネルバッファにフラッシュされるとtrue, バッファがいっぱいの場合はfalse
- falseをうけた場合はdrainイベントを利用
- drainイベントはカーネルバッファに空きができると発生するため、
- write()->'drain'->write()という形でwriteを再開する形式が一般的
//end()
- 書き込みを終了
- Bufferと文字列を渡すことができる
//destroy()
- ファイル記述子をcloseする
- 出力キューに溜まっていたデータは送信されない
//destroySoon()
- 出力キューのデータが空になった時点でファイル記述子をcloseする
-
プロパティ
-
writeableプロパティを確認することで読み込みの可否が判断できる
-
stream sample
var path = require('path'),
fs = require('fs');
var outputFilePath = path.join(__dirname, 'write.txt');
var writeStream = fs.createWriteStream(outputFilePath);
var inputFilePath = path.join(__dirname, 'read.txt');
var readStream = fs.createReadStream(inputFilePath);
writeStream.on('pipe', function(){
console.log('readableStream pipes writeStream');
})
writeStream.on('error', function(err){
console.log('error occured');
console.log(err);
});
writeStream.on('close', function(){
console.log('writable stream closed');
});
readStream.pipe(writeStream);
readStream.on('data', function(data){
console.log('>> data event occured');
});
readStream.on('end', function(){
console.log('read end');
});
readStream.on('error', function(err){
console.log('error occured');
console.log(err);
});
- バイナリデータを扱う際に利用する
- v8ヒープ外部でメモリを確保する
- Bufferはバイナリファイルの読み書きに利用する
- Bufferは文字列オブジェクトとして利用する
- デフォルトエンコーディングのUTF−8以外を利用する場合エンコーディングを指定して読み出す
- Bufferはグローバルクラスなのでコードの中でBufferクラスを利用することが可能
- Bufferオブジェクト作成時にサイズを引数に指定する
- オブジェクトを直接引数に指定する方法がある
- sample
$ cat buf.js
var size = 16;
var buf = new Buffer(size);
var arr = [1,2,3,4,5,6,7,8];
var arrayBuf = new Buffer(arr);
var str = "sample";
var stringBuf = new Buffer(str);
console.log(buf);
console.log(arrayBuf);
console.log(stringBuf);
$ node buf.js
<Buffer 00 a8 97 7a 02 00 00 00 00 63 72 65 61 74 65 50>
<Buffer 01 02 03 04 05 06 07 08>
<Buffer 73 61 6d 70 6c 65>
- 書き込み
- buf.write(string, [offset], [length], [encoding])
var a = 'test';
buf.write(a, 0, a.length, 'utf-8');
- Bufferの文字列利用
var str = 'sample';
buf.write(str);
console.log(buf.toString('utf-8', 0,4));
- Bufferの配列
var a = 'buff';
buf.write(a);
console.log(buf[0]);
- copy(), concat(), slice() APIが存在する
- var fs = require('fs') でファイルシステムモジュールを使用可能
- fs.writeFile(filename, data, [encoding], [callback]) �- 絶対パス、相対パスが使える
- 相対パスはスクリプトファイルからのパスではなく、process.cwd()が返すパスからの相対になる
- 第1引数:ファイルパス
- 第2引数:書き込む内容(string or bufferの形式)
- 第3引数:ファイルの文字コード(デフォルトはnull)
- 第4引数:コールバック
- fs.readFile(filename, [encoding], [callback])
- ファイルの内容を全て読み込む �- 絶対パス、相対パスが使える
- 相対パスはスクリプトファイルからのパスではなく、process.cwd()が返すパスからの相対になる
- 第1引数:ファイルパス
- 第2引数:ファイルの文字コード(デフォルトはnull)
- 第3引数:コールバック
var fs = require('fs');
fs.writeFile('target.txt', 'some data', 'utf8', function(err){
});