Node.js 在real-time tweet streamer socket.io应用程序上将标题发送到客户端后,无法设置标题
我正在node.js和react.js上创建一个实时twitter拖缆应用程序,在npm启动时遇到了这个错误。我已经修复了package.json文件,应用程序确实在localhost上打开,但是当这个错误弹出时,它会立即关闭。在package.json中,输入npm start时,npm run server和npm run client都会同时触发Node.js 在real-time tweet streamer socket.io应用程序上将标题发送到客户端后,无法设置标题,node.js,twitter,Node.js,Twitter,我正在node.js和react.js上创建一个实时twitter拖缆应用程序,在npm启动时遇到了这个错误。我已经修复了package.json文件,应用程序确实在localhost上打开,但是当这个错误弹出时,它会立即关闭。在package.json中,输入npm start时,npm run server和npm run client都会同时触发 [1] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sen
[1] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[1] at new NodeError (node:internal/errors:329:5)
[1] at ServerResponse.setHeader (node:_http_outgoing:573:11)
[1] at ServerResponse.header (D:\UCL\real-time-tweet-streamer\node_modules\express\lib\response.js:771:10)
[1] at ServerResponse.send (D:\UCL\real-time-tweet-streamer\node_modules\express\lib\response.js:170:12)
[1] at ServerResponse.json (D:\UCL\real-time-tweet-streamer\node_modules\express\lib\response.js:267:15)
[1] at ServerResponse.send (D:\UCL\real-time-tweet-streamer\node_modules\express\lib\response.js:158:21)
[1] at D:\UCL\real-time-tweet-streamer\server\server.js:77:9
[1] at processTicksAndRejections (node:internal/process/task_queues:94:5) {
[1] code: 'ERR_HTTP_HEADERS_SENT'
[1] }
[1] npm ERR! code 1
[1] npm ERR! path D:\UCL\real-time-tweet-streamer
[1] npm ERR! command failed
[1] npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c node server/server.js
下面是server.js中的代码
const express = require("express");
const bodyParser = require("body-parser");
const util = require("util");
const request = require("request");
const path = require("path");
const socketIo = require("socket.io");
const http = require("http");
const app = express();
let port = process.env.PORT || 3000;
const post = util.promisify(request.post);
const get = util.promisify(request.get);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const server = http.createServer(app);
const io = socketIo(server);
const BEARER_TOKEN = process.env.TWITTER_BEARER_TOKEN;
let timeout = 0;
const streamURL = new URL(
"https://api.twitter.com/2/tweets/search/stream?tweet.fields=context_annotations&expansions=author_id"
);
const rulesURL = new URL(
"https://api.twitter.com/2/tweets/search/stream/rules"
);
const errorMessage = {
title: "Please Wait",
detail: "Waiting for new Tweets to be posted...",
};
const authMessage = {
title: "Could not authenticate",
details: [
`Please make sure your bearer token is correct.
If using Glitch, remix this app and add it to the .env file`,
],
type: "https://developer.twitter.com/en/docs/authentication",
};
const sleep = async (delay) => {
return new Promise((resolve) => setTimeout(() => resolve(true), delay));
};
app.get("/api/rules", async (req, res) => {
if (!BEARER_TOKEN) {
res.status(400).send(authMessage);
}
const token = BEARER_TOKEN;
const requestConfig = {
url: rulesURL,
auth: {
bearer: token,
},
json: true,
};
try {
const response = await get(requestConfig);
if (response.statusCode !== 200) {
if (response.statusCode === 403) {
res.status(403).send(response.body);
} else {
throw new Error(response.body.error.message);
}
}
res.send(response);
} catch (e) {
res.send(e);
}
});
app.post("/api/rules", async (req, res) => {
if (!BEARER_TOKEN) {
res.status(400).send(authMessage);
}
const token = BEARER_TOKEN;
const requestConfig = {
url: rulesURL,
auth: {
bearer: token,
},
json: req.body,
};
try {
const response = await post(requestConfig);
if (response.statusCode === 200 || response.statusCode === 201) {
res.send(response);
} else {
throw new Error(response);
}
} catch (e) {
res.send(e);
}
});
const streamTweets = (socket, token) => {
let stream;
const config = {
url: streamURL,
auth: {
bearer: token,
},
timeout: 31000,
};
try {
const stream = request.get(config);
stream
.on("data", (data) => {
try {
const json = JSON.parse(data);
if (json.connection_issue) {
socket.emit("error", json);
reconnect(stream, socket, token);
} else {
if (json.data) {
socket.emit("tweet", json);
} else {
socket.emit("authError", json);
}
}
} catch (e) {
socket.emit("heartbeat");
}
})
.on("error", (error) => {
// Connection timed out
socket.emit("error", errorMessage);
reconnect(stream, socket, token);
});
} catch (e) {
socket.emit("authError", authMessage);
}
};
const reconnect = async (stream, socket, token) => {
timeout++;
stream.abort();
await sleep(2 ** timeout * 1000);
streamTweets(socket, token);
};
io.on("connection", async (socket) => {
try {
const token = BEARER_TOKEN;
io.emit("connect", "Client connected");
const stream = streamTweets(io, token);
} catch (e) {
io.emit("authError", authMessage);
}
});
console.log("NODE_ENV is", process.env.NODE_ENV);
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../build")));
app.get("*", (request, res) => {
res.sendFile(path.join(__dirname, "../build", "index.html"));
});
} else {
port = 3001;
}
server.listen(port, () => console.log(`Listening on port ${port}`));
如果有人能帮助我了解错误所在以及可能存在的解决方案,我将不胜感激。在您发送响应的每个位置之后,您需要返回
,这样您的函数就不会继续执行并导致它尝试发送另一个响应。我在/api/rules
路由中看到多个地方,在发送响应后需要添加返回
,因为如果不添加,即使您已经发送了响应,它也会执行res.end(response)
。这就是导致您看到的错误的原因。这工作非常好!现在,当应用程序查找新tweet时,控制台中会出现一个不同的错误。错误:CORS策略已阻止从源“”访问“”处的XMLHttpRequest:请求的资源上不存在“Access Control Allow origin”标头。@VanshAmbashta-这将是一个新问题的主题。如果您试图从不同于API主机域的网页访问API,则需要启用CORs支持。如果你需要帮助,最好研究一下如何做,然后开始一个新问题。请查看上面的链接