2017-03-20 17 views
1

Node.jsの再帰的非同期リクエストの動作に関する質問があります。Node.jsでの非同期再帰に関する問題

以下の機能は、MongoDBのからの検索結果を返すことを意図しています。最初の検索結果が空になったら、テキストを個々の単語に分割してから、resオブジェクトをパラメータとして渡して、各単語のfetchResult(...)を再帰的に試みます。

function fetchResult(text, res){ 
    var MongoClient = require('mongodb').MongoClient; 

    MongoClient.connect(mongoURL + "/search", function (err, db) { 

     if(err) throw err; 

     db.collection('results', function(err, collection) { 

      // search for match that "begins with" text 
      collection.findOne({'text':new RegExp('^' + text, 'i')}, function(err, items){ 

       var result = (items == null || items.result == null) ? "" : items; 

       if (result){ 
        res.send(result); 
       } 
       else { 
        // no result, so fire off individual word queries - if any spaces found 
        if (text.indexOf(' ') > -1){ 
         // split string into array 
         var textArray = text.split(" "); 

         // recursively process individual words 
         for (index = 0; index < textArray.length; index++) { 
          // ***** RACE CONDITION HERE? ***** 
          fetchResult(textArray[index], res); 
         } 
        } 
        else { 
         // just return empty result 
         res.send(result); 
        } 
       } 
      }); 
     }); 
    }); 
} 

は、私は、これはファンアウト非同期解像度を基準として、競合状態のビットを引き起こす可能性が疑われ、これは、私は、コードを実行したときに確認し、次のエラーが観察された:

Error: Can't set headers after they are sent. 
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11) 

だから私の質問は:どのように私は、個々の文字列を実行し、所望の再帰的な行動は、我々は(または検索が全く結果が返されないプロセスの終了時に)最初の結果を見つけたときにのみ返す、シーケンスでを照会達成することができますか?

+0

研究 – Deep

答えて

1

コードにはリファクタリングが必要です。

まず、fetchResult関数からMongoClient.connect呼び出しを削除。一度接続して後で使用するためにdbオブジェクトを保存することができます。

第二に、あなたのアプローチであなたは、クエリ内の各単語に対して応答を返すされています。私は再帰呼び出しがここに行く方法だとは思わない。

それがトリッキー取得する場所これは...あなたの最初のクエリが失敗した場合は、複数の非同期クエリを持って、あなたは何とか結果を集約する必要があります。私はMongoにはあまり慣れていませんが、find $inで結果のセットを検索することでこれを避けることができると信じています。 this questionを参照してください。それが今、再利用可能ですので、約束について

+0

おかげで、私が接続し、コレクションの作成を分離しました。どの時点で接続を終了するのですか? – HomerPlata

+0

私はあなたのコードの全体像を持っていませんが、fetchResultメソッドがリクエストメソッドから呼び出されたとします。あなたの接続をそこで管理することができます。 – mihai

+0

したがって、接続作成コードを呼び出しメソッドに移動する実際のメリットは何ですか? – HomerPlata