node.jsでノードファイバーを使用してデータベースコードの煩雑さを軽減する方法を模索してきましたが、機能させることができません。最小限のテストケースとして、コードをこれに要約しました。
var Future = require('fibers/future');
var pg=require('pg');
var connstr = "pg://not_the_real_user:or_password@localhost/db";
var pconnect = Future.wrap(pg.connect);
Fiber(function() {
var client = pconnect(connstr).wait();
console.log("called function");
}).run();
そのままにしておくと、次のエラーが発生します。
pgfuture.js:10
}).run();
^
TypeError: undefined is not a function
at Object.PG.connect.pools.(anonymous function).genericPool.Pool.create (/home/erik/code/treehouse-node/node_modules/pg/lib/index.js:49:20)
at dispense (/home/erik/code/treehouse-node/node_modules/pg/node_modules/generic-pool/lib/generic-pool.js:223:17)
at Object.exports.Pool.me.acquire (/home/erik/code/treehouse-node/node_modules/pg/node_modules/generic-pool/lib/generic-pool.js:267:5)
at PG.connect (/home/erik/code/treehouse-node/node_modules/pg/lib/index.js:75:15)
at Future.wrap (/home/erik/code/treehouse-node/node_modules/fibers/future.js:30:6)
at /home/erik/code/treehouse-node/pgfuture.js:8:18
ただし、pconnectを呼び出す行をコメントアウトすると、コンソールに「呼び出された関数」メッセージが表示され、エラーは発生しません。githubページの例はほぼ同じ構造であり、私のシステムでは正しく機能しますが、ここで間違っていることに困惑しています。
編集:追加の詳細
私は、無関係に見える2つの異なる方法で、流行の後にコードを実行することに成功しましたが、どちらも同じ動作をします。関数が終了した後、ノードがハングするだけで、ctrl-cを使用してノードを強制終了する必要があります。その結果を得るために私が行った2つのことは次のとおりです。
1)pg.connectを無名関数でラップし、それをFutureでラップします。
pconnect = Future.wrap(function(err,cb){pg.connect(err,cb);});
2)これは本当の謎ですが、同じ結果になるようです。ファイバー内では、pconnectを呼び出す前に直接pg.connectを呼び出すだけで、すべてがうまくいくようです。
// add this line before call to pconnect
pg.connect(connstr, function(e,c){console.log("connected.");});
// and now the original call to pconnect
var client = pconnect(connstr).wait();
たとえば、pg.connect関数に、Future.wrap呼び出しの予想されるレイアウトを何らかの形で妨害する他のオプションの引数がある場合、(1)が意味をなす状況を想像できます。もう1つの可能性は、オブジェクトがスコープ外になり、pconnectへの実際の呼び出しが行われたときに「this」参照が定義されていないことです。しかし、なぜ(2)が効果があるのか理解できません。
編集:部分的な答え
さて、私は質問の少なくとも一部に答えました。オブジェクトスコープについての私が持っていた考えは正しいことが判明し、bind()関数を使用することで、コールバックラッピングの余分なレイヤーを排除することができました。
var pconnect = Future.wrap(pg.connect.bind(pg));
ただし、不明な理由により、実行の最後にハングします。