2016-03-25 9 views
1

次のコードでは、queryStringという選択クエリがあり、データベースに既に格納されている一部のツイートに関する情報を取得しています。私が何をしたかノードJS別のクエリに依存するMySQLクエリ

var queryString = 'select Tweet.Label, Tweet.TDate, Tweet.TLink, Author.Lable, Author.ALink from Tweet, Author where Tweet.AuthorID IN (select ID from Author where Lable = ?) AND Author.ID IN (select ID from Author where Lable = ?)'; 
var query = connection.query(queryString, [term,term], function(err, rows) { 
     console.log(rows); 
     //res.write(JSON.stringify(rows)); 
     var tweet = JSON.parse(JSON.stringify(rows)); 
     for(var i in tweet){ 
      res.write("Author: "); 
      res.write("<a href='" + tweet[i].ALink + "' target='_blank'>" + tweet[i].Lable + "</a> <br/>"); 
      res.write("Date: " + tweet[i].TDate + "<br/>"); 
      res.write("Tweet: " + "<a href='" + tweet[i].TLink + "' target='_blank'>" + tweet[i].Label + "</a> <br/>"); 
      var query1 = connection.query('select Label from Hashtag where ID IN (select HashID from tweethashs where TweetID IN (select ID from Tweet where Label = ?))', [tweet[i].Label], function(err, rows1) { 
        var tweet1 = JSON.parse(JSON.stringify(rows1)); 
        for(var i in tweet1){ 
         res.write("Hashtag: "); 
         res.write(tweet1[i].Label); 
        } 
       } 
      ); 
      res.write("<br/><br/>"); 
     } 

     res.end(); 
    }); 

は私がのループ内のハッシュタグのクエリが含まれている:私はそのハッシュタグとともにユーザーにつぶやき情報を表示するように、私はそれらのツイートで言及されているハッシュタグを検索したいですつぶやきのように、私はハットタグクエリのためのパラメータとしてツイートを取る(where節)。私は、コードを実行すると、私は次のエラーを得た:

events.js:154 
     throw er; // Unhandled 'error' event 
    ^

Error: write after end 
    at ServerResponse.OutgoingMessage.write (_http_outgoing.js:426:15) 
    at Query._callback (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\ 
Node JS\SocialSearch.js:58:11) 
    at Query.Sequence.end (C:\Users\Nasser\Desktop\Spring Semester\Intelligent W 
eb\Node JS\node_modules\mysql\lib\protocol\sequences\Sequence.js:96:24) 
    at Query._handleFinalResultPacket (C:\Users\Nasser\Desktop\Spring Semester\I 
ntelligent Web\Node JS\node_modules\mysql\lib\protocol\sequences\Query.js:144:8) 

    at Query.EofPacket (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\ 
Node JS\node_modules\mysql\lib\protocol\sequences\Query.js:128:8) 
    at Protocol._parsePacket (C:\Users\Nasser\Desktop\Spring Semester\Intelligen 
t Web\Node JS\node_modules\mysql\lib\protocol\Protocol.js:280:23) 
    at Parser.write (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\Nod 
e JS\node_modules\mysql\lib\protocol\Parser.js:73:12) 
    at Protocol.write (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\N 
ode JS\node_modules\mysql\lib\protocol\Protocol.js:39:16) 
    at Socket.<anonymous> (C:\Users\Nasser\Desktop\Spring Semester\Intelligent W 
eb\Node JS\node_modules\mysql\lib\Connection.js:96:28) 
    at emitOne (events.js:90:13) 

誰かが基本的にあなたのためのループ内の複数の非同期デシベルクエリを作る、しかしとき、同期、あなたの応答を閉じて、私はこの問題

答えて

1

の解決に役立つことができますforループが終了しています.dbクエリが終了すると、既に閉じられているレスポンスに書き込もうとします。

var queryString = 'select Tweet.Label, Tweet.TDate, Tweet.TLink, Author.Lable, Author.ALink from Tweet, Author where Tweet.AuthorID IN (select ID from Author where Lable = ?) AND Author.ID IN (select ID from Author where Lable = ?)'; 
     var query = connection.query(queryString, [term,term], function(err, rows) { 
     console.log(rows); 
     //res.write(JSON.stringify(rows)); 
     var tweets = JSON.parse(JSON.stringify(rows)); 
     var queries_made = 0; 
     var queries_success = 0; 
     tweets.forEach(function(tweet){ 
      connection.query('select Label from Hashtag where ID IN (select HashID from tweethashs where TweetID IN (select ID from Tweet where Label = ?))', [tweet.Label], function(err, rows1) { 
        res.write("Author: "); 
        res.write("<a href='" + tweet.ALink + "' target='_blank'>" + tweet.Lable + "</a> <br/>"); 
        res.write("Date: " + tweet.TDate + "<br/>"); 
        res.write("Tweet: " + "<a href='" + tweet.TLink + "' target='_blank'>" + tweet.Label + "</a> <br/>"); 

        var tweet1 = JSON.parse(JSON.stringify(rows1)); 
        for(var j in tweet1){ 
         res.write("Hashtag: "); 
         res.write(tweet1[j].Label); 
        } 
        res.write("<br/><br/>"); 
        queries_success++; 
        if(queries_made==queries_success) 
         res.end(); 
       } 
      ); 
      queries_made++; 

     }) 

    }); 

リクエストしたdbクエリと返信したクエリを追跡する2つのカウンタを追加しました。これら2つのカウンタが等しい場合、すべてのdbトランザクションと応答書き込みが完了し、応答ストリームを閉じることができます。

これはベストプラクティスではありませんが、 asyncモジュールをチェックするか、dbクエリでpromisesを使用してみてください。

編集 内部クエリが完了すると書き込みが発生するようにコードを変更しました。書き込みの順序は最初のクエリの順序を尊重するのではなく、最初に内側のクエリが終了するかどうかに基づいて記述されるため、今は注意してください。私はこれを達成する最善の方法ではないことをあなたに伝える必要があります。そして、あなたは私が前に言った非同期モジュールと約束を読む必要があります。また、javascriptで非同期操作と同期操作を混在させる方法を見てみましょう!

+0

ありがとうございました。 '著者: 日: さえずる: ハッシュタグ: 著者:B 日:B さえずる:B ハッシュタグ: 覇者HashB' ようなことは、現在の出力が同じように印刷されていますハッシュタグは最後に表示されます。私はなぜ彼らは彼らのつぶやきで印刷されていないのだろうかと疑問に思っています。例えば、HashAはツイートAで印刷されなければなりません。 – Nasser

+0

ありがとう。それは今働く。感謝します。 – Nasser

0

res.end()を停止してこれを行う場合、あなたの応答が配列内のツイートの順序と同じ順序で書き込まれるかどうかはわかりません。

forループは同期ですが、クエリが非同期であるため、以前よりも早く終了する可能性があります。理論的には書き込みがランダムに起こる結果となります。

あなたが使用できるものはasync.mapです。より良い、これは最初のasync.mapコードを読み、理解するには:

注:

基本的には、代わりにそのforeachループの次のコードのようなものを置くことができます。

//the tweet for which I get the information from DB 
var getTweetInfo = function(tweet, callback){ 
    con.query(query, function(err, tweetInformation){ 
     if(err) { 
      console.log(err); 
      //with this you are passing the error back into the async.map function. Otherwise it would be lost (Bad javascript :P) 
      callback("Error getting tweets" + err); 
     } 
     else{ 
      //in here you can make any changes to the tweet information before sending it as a response 

      //this will send the tweetInformation into the results array 
      callback(null, tweetInformation); 
     } 
    }); 
} 

//tweetsArray is the array with tweets 
//getTweeetInfo is a function that will get each tweet from the tweets array and will apply the query to it 
async.map(tweetsArray, getTweetInfo, function(error, tweetInformationArray){ 
    if (error) { 
     console.log(error); 
    }else{ 
     //'results' will hold an array with the information for each tweet in the same order as the initial tweets 
     res.json({ 
      response: tweetInformationArray 
     }); 
    } 
}) 

この後、フロントエンドで応答を解析できます。データは、非同期(イベントループを待機させない)から構成されています。つまり、それを通過して画面にうまく表示できます。

関連する問題