Node JS MySQL查询依赖于另一个查询

时间:2016-03-25 11:43:06

标签: mysql node.js

在下面的代码中,我有一个名为queryString的select查询,它检索有关已存储在数据库中的一些推文的信息。我想检索这些推文中提到的主题标签,以便向用户显示推文信息及其主题标签:

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)

有人可以帮我解决这个问题

2 个答案:

答案 0 :(得分:1)

基本上你在for循环中做了几个异步数据库查询,但是当同步for循环结束时你关闭了你的响应。所以当db查询结束时你试着写一个已经关闭的响应。

   <div class="header with-bord">
     <h3 class="title">New Message <a (click)="closeEmail()" class="close"><i class="fa fa-times"></i></a></h3>
    </div>

我添加了两个计数器,它将跟踪您请求的数据库查询和已回复的查询。当这两个计数器相等时,所有数据库事务和响应写入都已完成,因此您可以关闭响应流。

虽然这不是最佳做法。您应该检查async模块或尝试在数据库查询中使用promises

修改 我更改了代码,以便在内部查询完成时发生写入。现在要小心,因为写入的顺序不会遵循第一个查询的顺序,但它会根据内部查询首先结束的内容进行写入。我必须告诉你,这不是实现这一目标的最佳方式,你需要阅读异步模块和我之前告诉你的承诺。另请参阅如何在javascript中混合异步和同步操作!

答案 1 :(得分: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
         });
     }
})

在此之后,您可以解析前端的响应。数据是由异步组成的(你没有让事件循环等待),这意味着你可以通过它并在屏幕上很好地显示它。