【发布时间】:2018-07-08 21:23:41
【问题描述】:
以下代码在第一次执行时按预期工作。第二次通过它失败并出现以下错误:Error: Can't set headers after they are sent.
基本上,我试图从一系列已发布的 mqtt 主题中返回一条消息。我已经尝试了几种方法来做到这一点,但对这种行为感到茫然。下面的代码显示了使用 this MDN 文章中详述的 Promise 的尝试。我也尝试过使用 async / await(如果需要,我也可以发布此代码)。
概念
get 请求从网页到达,这会触发将 mqtt 消息发布到本地代理。一个单独的端点正在侦听此主题。在这种情况下,一个带有连接网络摄像头的树莓派。主题被接收到 rpi 做它的事情并发布带有 url 作为它的数据的返回消息。初始 mqtt 发布者正在侦听此响应并触发 res.json() 作为响应。
这第一次有效,当我刷新网页时,它在发送后失败并显示无法标头。如何重置资源?看来是这样的。
punchitRoute.js
const express = require('express');
const punchitRoute = express.Router();
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://192.168.88.54:1883');
client.subscribe('returned', function(){
console.log('subscribed');
})
async function img(){
return new Promise(resolve =>{ client.on('message', function(topic, url){
const message = {
url: url.toString(),
name: "garfield",
date: Date.now()
}
return message;
})
})
}
punchitRoute.get('/', async function(req, res){
const mess = await img();
console.log(mess);
res.json(mess);
});
module.exports = punchitRoute;
server.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const punchit = require('./routes/punchitRoute');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended:false }));
app.get("/", (req, res) => {
res.json({
name: "Express application",
message: "welcome to punchit"
})
});
app.use('/api/punchit', punchit);
const PORT = process.env.PORT || 6040;
app.listen(PORT);
console.log('server started on: ', PORT);
我的猜测是,我错过了关于使用 express 请求的基本生活事实。
提前感谢您的任何指导。
【问题讨论】:
-
对于初学者来说,你的
img()函数永远不会调用resolve()来解决它的承诺。 -
其次,每次调用
img()时,都会为client.on('message', ...)添加另一个事件处理程序。这些会堆积起来,你会有重复的,你会尝试多次回复相同的消息。通常,promise 不适合事件处理程序,因为如果多次调用函数会出现顺序问题,但如果您打算以这种方式使用它们,则必须在事件处理程序触发后删除它。即便如此,仍有问题需要解决。 -
感谢您的回复。在这种情况下使用 async / await 会更好吗?
-
老实说,您的代码太混乱了,我无法真正建议您应该做什么。您需要提供您想要完成的任务的完整描述(用文字而不是代码),以便我们可以从头开始建议最好的实现。
async/await不会解决我评论过的任何问题。 -
confused 是一种很好的表达方式。上面的代码是错误的,我复制的文件是在没有测试的情况下编辑的,当我终于意识到我没有在测试中调用这个文件并切换它时,上面的代码在几个方面都失败了。我将重新发布对代码的编辑并重新描述目标。