0

Node.js / node-postgres lib / PostgreDB を使用して RESTful サービスを実装する際に 2 つの問題があり、どちらも JS の非同期性が原因です。

A) client.query(query, callback)呼び出しで追加の引数をコールバックに渡す必要があります

私はクエリのコールバック内にいて、DB から最近フェッチされた行の配列を調べており、それらのそれぞれに対して後続のクエリを起動したいと考えています。

var query =  client.query('SELECT * FROM event', queryAllEventsHandler);
function queryAllEventsHandler(err, result){        
   allEvents = result.rows;

   /* allEvents is an JSON array with the following format
   [  {"id_event":1, "name":"name of the event"}, 
      {"id_event":1, "name":"name of the event"} 
   ]
   */

for(var i = 0; i<allEvents.length; i++){
     client.query('SELECT * FROM days where id_event = $1',[allEvents[i].id_event], function( err, result){
               //I want to have a reference to variable i
     }
}

上記の例では、次のようなことをしたいと考えています。

client.query('SELECT * FROM days where id_event = $1',[allEvents[i].id_event], function( AN_EXTRA_ARG, err, result)

AN_EXTRA_ARG がコールバック関数の追加の引数またはクロージャーである場合...どうすればこれを達成できますか? of iでクロージャを作成し、それをコールバックの引数として渡す必要がありますか? どのように ?:|

B) クエリの「同期」

さまざまなクエリを起動し、それらすべてからカスタム JSON を作成する必要があります。すべてのクエリとそのコールバックは非同期 (誰も待っていない) であるため、それを「飼いならす」方法を探していました。他のものの中で、最初に思いついた解決策を見つけましたが、少し「悪い/お粗末」に見えました。 ": @jslattsがNode.js を使用した同期データベース クエリで示唆しているように、クエリ カウントを維持することは実際に進むべき道です。

ホープ・アイ

4

4 に答える 4

1

私の質問に答えるのは好きではありませんが、これは誰かにとって興味深いかもしれません....私の質問のA部分について。関数でこれにカスタム オブジェクトを割り当てることができます。

ご存知のように、これは関数内の Window (top) オブジェクトに対応します (メソッド関数でない限り)。bind 関数を使用すると、これの参照を独自のオブジェクトに変更できます...

だから私がしたことは、名前付き関数queryCallbackを作成したことです

function queryCallback(err, result){
        //this == Window (default)             
}

匿名のコールバック関数を名前付きのqueryCallbackに変更しました:

client.query('SELECT * ... where id_event = $1',[allEvents[i].id_event], queryCallback.bind( {"position":i},  err, result));

ここで、queryCallback.bind( {"position":i}, err, result));に注意してください。

bind(my_custom_this, [other args])が行うことは、バインドが呼び出された関数内でカスタム オブジェクト (私の場合は {"position":i}) をthisにバインドすることです...

これで、次のシナリオができました。

function queryCallback(err, result){
            //this == {"position":i}
}

バインドの説明: http://fitzgeraldnick.com/weblog/26/

于 2013-06-25T11:59:04.943 に答える
1

質問 A に関しては、両方のクエリを処理し、最後のクエリが実行されたときにのみ戻り、両方の結果をコールバックに返す関数を作成できます。

for(var i = 0; i<allEvents.length; i++){
  query(client, allEvents[i], function(result1, result2) {
    //do something
  });   
}

function query(client, event, callback) {
    client.query('SELECT * FROM days where id_event = $1',[event.id_event], function( err1, result1){
        client.query('SELECT * FROM days where id_event = $1',[event.id_event], function( err2, result2){
          callback(result1, result2);
        });
     });
}
于 2013-06-25T11:24:09.407 に答える
0

A) 個人的には、これにはlodash (または必要に応じてアンダースコア) が気に入っpartial()ています。関数といくつかの引数を取り、指定された引数が適用され、残りの引数がまだ開いている関数を返します。これは、カリー化の機能的な概念によく似ています。

B) 複数の非同期結果を組み合わせるには、asyncを強くお勧めします。構文に慣れるには少し時間がかかりますが、このような作業は非常に簡単です。簡単なサンプル:

async.parallel([
    one: function(callback){
        db.fetch(options, callback);
    },
    two: function(callback){
        db.fetch(options, callback);
    }
],
function(err, results){
    // this callback will get called when either parallel call gives an error
    // or when both have called the callback
    if (err) {
        // handle error
        return;
    }

    // get the results from results.one and results.two
});

==編集で追加==

実際、lodash は、(関数呼び出しのため) 少し高価ではありますが、問題 A) に対してより優れた (imho) ソリューションも提供します。

_(allEvents).each(function(event, index, array) {
    client.query('SELECT * FROM days where id_event = $1',[event.id_event], function( err, result) {
         // Just use 'index' here, which doesn't change during the each
     }
});
于 2013-06-25T11:04:45.707 に答える
0

B) の場合、オプションには非同期または Promise ライブラリ経由 (Q、when.js、Bluebird など) が含まれます。

于 2015-01-16T15:45:21.990 に答える