2016-03-25 109 views
1

在下面的代碼中,我有一個名爲queryString的選擇查詢,該查詢檢索有關已存儲在數據庫中的一些tweets的信息。我想取回了在這些微博中提到的主題標籤,讓我展示給用戶的tweet信息與它的主題標籤一起:Node 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(); 
    }); 

我所做的是我包括用於循環內的主題標籤查詢推文,以便我將推文作爲hashtags查詢的參數(在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查詢和已回覆的查詢。當這兩個計數器相等時,所有數據庫事務和響應寫入都已完成,因此您可以關閉響應流。

雖然這不是最佳實踐。您應該檢查async模塊或嘗試使用promises與您的數據庫查詢。

編輯 我改變了代碼,以便在內部查詢完成時發生寫入。現在要小心,因爲寫入的順序不會考慮第一個查詢的順序,但它會根據內部查詢首先結束的內容進行寫入。我必須告訴你,這不是實現這個目標的最好方法,你需要閱讀異步模塊和我以前告訴過你的承諾。另外看看如何在JavaScript中混合使用異步和同步操作!

+0

謝謝你的幫助。的東西現在的輸出被印刷像: '著者:甲 日期:甲 鳴叫:甲 主題標記: 著者:乙 日期:乙 鳴叫:乙 主題標記: 波沙HashB' 作爲你可以看到,標籤在最後打印。我想知道他們爲什麼不打印他們的推文,例如HashA應該印有推文A等 – Nasser

+0

謝謝。它現在有效。欣賞它。 – Nasser

0

如果您選擇通過停止res.end()來做到這一點,那麼您不確定您的響應是否會以與推文位於數組中相同的順序進行書寫。

for循環是同步的,但查詢是異步的,這意味着它們可以比之前啓動的更快。這將導致寫入在隨機發生的理論上。

你可以使用的是一個async.map。

基本上,而不是foreach循環就可以把類似下面的代碼:

注:爲了更好地理解這首先閱讀async.map代碼。

//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 
     }); 
    } 
}) 

之後,您可以解析前端的響應。數據是組成的,異步的(你不保持事件循環等待),這意味着你可以通過它並在屏幕上很好地顯示它。

相關問題