【发布时间】:2021-08-29 14:53:56
【问题描述】:
我正在将我的 PHP/MySQL 代码转换为 NodeJS。但是我被困在 While 循环中,不知道在哪里返回数据。这是代码;
var mysql = require("mysql");
var express = require("express");
var jwt = require("jsonwebtoken");
var config = require("../config");
var connection = require("../database");
var getFCM = function (req, res) {
const bodyuserid = req.body.id;
var query = "SELECT ?? FROM ?? WHERE userid = ? ";
var table = ["audioid", "subscribe", bodyuserid];
query = mysql.format(query, table);
connection.query(query, function (err, rows) {
if (err) {
res.json({ Error: true, Message: "Error executing MySQL query" });
} else {
var n = 0;
var thislength = rows.length;
var newaudioid = rows[n].audioid;
var query = `SELECT ap.audioid, ap.title, us.name FROM audioposts ap INNER JOIN audioposts a2 ON a2.audioid = ap.opid INNER JOIN accounts us ON us.id = a2.userid WHERE ap.opid = ? AND ap.opid <> 0`;
var table = [newaudioid];
query = mysql.format(query, table);
while (n < thislength) {
connection.query(query, function (err, data) {
if (err) {
res.json({ Error: true, Message: "Error executing MySQL query" });
} else {
console.log(data);
res.json(data);
}
});
n++;
}
}
});
};
module.exports = getFCM;
所以第一个查询从某个userid的subscribe表中选择所有audioids。
下一个查询从第一个查询中获取结果 audioid,并从 audiopost 表中获取所有帖子,其中每个结果 audioid 都是原始帖子 ID (opid)。
代码几乎可以运行,但没有为第二个查询的每个结果返回所需的标题、名称和音频。相反,它只返回一个结果。即;
[
{
"audioid": 147,
"title": "Goat Heaven",
"name": "Josie Jones"
}
]
如何让循环返回正确的 JSON 数据?
这是 NodeJS 控制台中的错误消息;
[
RowDataPacket {
audioid: 147,
title: 'Goat Heaven',
name: 'Josie Jones'
}
]
/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Login-API/node_modules/mysql/li b/protocol/Parser.js:437
throw err; // Rethrow non-MySQL errors
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the cli ent
at ServerResponse.setHeader (_http_outgoing.js:561:11)
at ServerResponse.header (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-L ogin-API/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Log in-API/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Log in-API/node_modules/express/lib/response.js:267:15)
at Query.<anonymous> (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Login -API/middleware/getFCM.js:34:10)
at Query.<anonymous> (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Login -API/node_modules/mysql/lib/Connection.js:526:10)
at Query._callback (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Login-A PI/node_modules/mysql/lib/Connection.js:488:16)
at Query.Sequence.end (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Logi n-API/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)
at Query._handleFinalResultPacket (/opt/bitnami/apache/htdocs/Node-MySQL-JWT -Signup-Login-API/node_modules/mysql/lib/protocol/sequences/Query.js:149:8)
at Query.EofPacket (/opt/bitnami/apache/htdocs/Node-MySQL-JWT-Signup-Login-A PI/node_modules/mysql/lib/protocol/sequences/Query.js:133:8) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
【问题讨论】:
-
陷入这样的循环,从客户端代码对数据库进行大量单独调用,保证会降低性能。更糟糕的是,这是一个网络应用程序,它显然是。
-
你会建议什么?
-
好吧,如果可能的话,我建议同时运行多个查询。 MySQL 的语法使得插入等操作非常容易。对于选择,您只需用分号分隔语句,您将收到多个结果集。当然,如果您只是将选择标准替换为 SQL 字符串,则存在 SQL 注入攻击的风险。有一些方法可以使用准备好的语句来做到这一点,但我实际上并没有从 node.js 做到这一点,所以我不能 100% 确定实用性。一般原则是每次拨打电话都会有很大的开销......
-
...到数据库。在许多情况下,调用的开销可能大于执行查询本身的开销。因此,如果您陷入循环并一遍又一遍地执行此操作,那么您将增加大量的性能抢夺开销。最好在客户端聚合查询并将它们作为一批发送。然而;我也很实用。如果这是几个查询,而不是数千个,我不会太担心。这种循环并不少见,因为这是最容易做的事情。您在这里遇到的基本问题是每个 HTTP 请求只能调用 res.json() 一次。
标签: javascript php mysql node.js