段々使える感じになってきたので、自宅でシコシコと開発しているNode.js用モジュール「Tikitaka」をGitHub 上に公開し、npmモジュールとして登録しました。
「Tikitaka」は、サーバー(Node.js)・クライアント(ブラウザ)上のオブジェクトやファンクションを、接続対象のクライアント・サーバから、 あたかもローカルにあるかのように 操作できるようにしてくれる、國村隼さん並に激渋なモジュールです。
例えば、こんなことができます。
- サーバ(Node.js)側スクリプト
function DBSample(){};
DBSample.prototype.get = function(key, client_func) {
// keyからvalueを得る"db.get"というものがあるものとして・・・
db.get(key,function(val) {
client_func(val); // クライアントから受け取ったfunction(のスタブ)呼び出し
});
}
- クライアント(ブラウザ)側スクリプト
var dbsamp = new DBSample();
dbsamp.get(1, function(v){
alert(v + 'だぞ'); // DBから受け取った値が出るはず!
});
動作するブラウザ等の情報は、GitHubの方に間違いだらけの英語で記載していますので、そちらを参照ください。
- GitHub
で、どんな感じで使うの?
インストール
まずは、こんな感じでお手軽かつお気軽にインストールしてください。
npm install tikitaka
サーバ側準備
httpサーバの準備
Tikitakaは、websocketを使用してクライアントと通信します。
websocketにはhttp接続が必要になりますので、Node.jsのhttpモジュールを使用して、httpサーバを隆々とした感じにおっ立ててください。
// sample
var http = require('http');
var fs = require('fs');
var sv = http.createServer(function(req,res) {
if (req.url=='/') {
fs.readFile('index.html', function(err, data)
{
res.end(data);
});
}
}).listen(8000, function(){});
クライアントに公開するモジュールの準備
クライアントに公開する(接続の起点となる)クラスを準備します。
コンストラクタfunctionとprototypeの構成でnewして使う形態にしてください。
namespaceの形のものは、tikitakaは両腕を組んで断固拒否するでしょう。
// sample
// これ、おれ、動く
function Dog() {}
Dog.prototype.calc = function( arr, callback ) {
var v = 0, r = '';
for ( var i in arr ) {
v += arr[i];
}
for ( var i=0; i<v; i++ ) {
r += 'ワン!! ';
}
callback(r);
}
// この形はウゴカナーイ
var Chimp = {
calc : function( arr, callback ) {
callback('ワタシニホンゴワカリマセン');
}
};
初期化
Tikitakaに下記をパラメータとして与えて初期化します。
- httpモジュール
- 公開するクラス
初期化の段階で、こいつは内部にwebsocketサーバを立ち上げます。そこんとこシクヨロでお願いいたします。
// 先頭に
var Tikitaka = require('tikitaka').Server;
var tikitaka = new Tikitaka();
// どこでもいいんで、httpモジュールのインスタンスが受け取れる場所で
tikitaka.init(http, {Dog:Dog /* , Cat:Cat...."クライアント側公開名:実体"*/ });
クライアント側tikitakaモジュールの準備
Tikitakaは、initに渡された情報を基にクライアント用javascriptを生成します。
そいつを、人の道に反する手段を使ってでも何しても構いませんので、なんとかしてクライアントに渡してください。
こんな感じで
var sv = http.createServer(function(req,res) {
if (req.url=='/test.js') {
res.end(tikitaka.getScript()); // tikitakaからスクリプト文字列を受け取ってresponseとして送信
}
...
サーバ側は以上!
クライアント側準備
TikitakaクライアントJavaScriptの読み込み
Tikitakaが生成したjavascript(サーバ側でtikitaka.getScript()で受け取ったもの)を、こっそりと受け取ってください。
たとえば
<script src='/test.js'></script>
使いまくる
window.addEventListener('load', function() {
var dog,
arr = [1,2,3];
dog = new Dog();
dog.calc(arr, function(a){alert(a); });
});
以上!
備考
非同期です!
このライブラリで生成されたモジュールは、非同期でやりとりを行います。
よって、返り値は受け取れません。
通信対象から結果を受け取るには、コールバックfunctionをパラメータとして設定し、呼び出し先からそのfunctionを呼び出してもらう形にする必要があります。(いつもの非同期処理の記載でOKです)
// NG
var a = svobj.func(); // サーバ側の返り値は受け取れません
// OK
svobj.func(func(v) {
// v:サーバから受け取った値
});
非同期で動くなら、newしてすぐにそのメンバをよんじゃだめなんじゃないの?
このライブラリには、newしてから通信対象から生成通知がくるまでの間に呼ばれたメンバをキューイングして、生成通知がきたときに順時実行する仕組みが含まれています。ですので、newについては、同期処理のような記載で問題ありません。
// こうしなくてよい。というか動かない var a = new SvObj( function() { a.test(); }); // これ、ワシ、動く a = new SvObj(); a.test();
受け取ったオブジェクトの変更は反映されません!
パラメータとしてobjectを渡すことはできますが、そのメンバを変更しても、相手側には反映されません。
// クライアント
var svobj = new SvObj();
var o = {
a : 1, // こいつを2にしたい!
b : function(v) {
this.a = v;
}
};
svobj.func(o)
// サーバ
function SvObj(){}
SvObj.prototype.func = function(obj) {
console.log(obj.a); // 1と出力される
obj.a = 2; // クライアントには反映されない
obj.b(2); // これなら反映される
}
おわりに
まだ生後3週間のライブラリなので、使っていただける方は、恐る恐る使っていただけると幸いです。
そして、動かなかった情報(オブラートに包んだ感じの表現で)、こうしたほうがよい情報(特にセキュリティ的な部分で)等をフィードバックしていただけると、ボクの弛んだ表情筋にスイッチが入ります。