Javascript 错误[ERR\u HTTP\u HEADERS\u SENT]:发送到客户端后无法设置头(POST方法)
我对Node很陌生;我查了一下,但不懂一些术语 代码的目的:URL缩短器post方法 我之所以出现此错误,是因为我试图将一个具有未定义DNS地址的URL发布到MongoDB(例如,通过了https的正则表达式测试,但出现以下错误) 模式和模型:Javascript 错误[ERR\u HTTP\u HEADERS\u SENT]:发送到客户端后无法设置头(POST方法),javascript,node.js,express,Javascript,Node.js,Express,我对Node很陌生;我查了一下,但不懂一些术语 代码的目的:URL缩短器post方法 我之所以出现此错误,是因为我试图将一个具有未定义DNS地址的URL发布到MongoDB(例如,通过了https的正则表达式测试,但出现以下错误) 模式和模型: var urlSchema = new mongoose.Schema({ url: String, shortUrl: String }); var Url = mongoose.model("Url", urlSchema
var urlSchema = new mongoose.Schema({
url: String,
shortUrl: String
});
var Url = mongoose.model("Url", urlSchema);
post处理程序的代码:
app.post("/api/shorturl/new", function(req, res) {
var url = req.body.url;
console.log(url);
var httpRegex = /^(https?:\/\/)/;
if (!httpRegex.test(url)) {
res.json({ error: "invalid url" });
return;
}
if (/^(https:\/\/)/.test(url)) {
var httpsDroppedUrl = url.slice(8);
dns.lookup(httpsDroppedUrl, function(err, address, family) {
console.log("address: %j family: IPv%s", address, family);
if (address == undefined) {
res.json({ error: "invalid url" });
return;
}
});
} else {
var httpDroppedUrl = url.slice(7);
dns.lookup(httpDroppedUrl, function(err, address, family) {
console.log("address: %j family: IPv%s", address, family);
if (address == undefined) {
res.json({ error: "invalid url" });
return;
}
});
}
var newUrl =
(Math.floor(Math.sqrt(url.length)) * 3).toString() +
+Math.floor(Math.random() * 9999).toString() +
Math.floor(Math.random() * 500).toString(); //random method to generate unique identifier
console.log(newUrl);
var data = new Url({
url: url,
shortUrl: newUrl
});
data.save(function(err) {
if (err) {
res.send("Error; please try again");
}
});
res.json(data);
});
以下是我得到的完整错误:
_http_outgoing.js:467
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:467:11)
at ServerResponse.header (/rbd/pnpm-volume/10bcf34e-5673-48ca-b962-5eaef435922b/node_modules/.registry.npmjs.org/express/4.17.1/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/rbd/pnpm-volume/10bcf34e-5673-48ca-b962-5eaef435922b/node_modules/.registry.npmjs.org/express/4.17.1/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/rbd/pnpm-volume/10bcf34e-5673-48ca-b962-5eaef435922b/node_modules/.registry.npmjs.org/express/4.17.1/node_modules/express/lib/response.js:267:15)
at /app/server.js:58:13
at processTicksAndRejections (internal/process/task_queues.js:83:17)
编辑1:next()
替换为return
我不确定我的代码哪里出错了您需要将所有
next()
调用替换为return
,因为:
res.send/json
之后不需要next()
——它们已经设置了状态并向客户端发送响应res.send/json
之后添加return
,因为调用res.send/json
不会立即从此处理程序返回您dns.lookup
调用转换为异步函数,因为现在它们不等待结果,并且立即继续执行
函数dnsLookup(url){
返回新承诺((解决、拒绝)=>{
查找(url、函数(错误、地址、族){
console.log(“地址:%j系列:IPv%s”,地址,系列);
如果(地址==未定义){
//您可以在这里调用reject(新错误(“无效url”),并在外部函数中捕获它
解析({错误:“无效url”});
返回;
}
解决();
});
}
}
if(/^(https:\/\/)/.test(url)){
var httpsdroppedrl=url.slice(8);
const lookupResult=等待dnsLookup(httpsdroppedrl);
if(lookupResult.error){
res.json({error:lookupResult.error});
返回;
}
}
当您使用res.json
时,您不需要调用next()
,因为请求-响应循环已经结束。next()
用于您希望请求内容通过请求和响应之间的多个中间件。我尝试删除所有next())调用,但其行为相同。出于某种原因,var-httpsdroppedrl=url.slice(8);
直接在var-newUrl=(Math.floor(Math.sqrt(url.length))*3.toString()++Math.floor(Math.random()*9999).toString()+Math.floor(Math.random()*500).toString();console.log(newUrl)之前执行;
然后它在dns.lookup内部进行回调。为什么它会从httpsdrookedURL跳到新URL,然后再跳回到dns.lookup?我怀疑lookup
是一个异步函数,这意味着它在后台执行,直到得到结果,而不依赖它的其余代码会继续运行继续执行。我同意Anatoly下面的回答。当你有多个res.json
时,你需要将return
放在它们前面,除了最后一个。有没有办法将剩余代码的执行延迟到异步函数完成执行之后?我替换了每个next()
使用返回
但是我仍然面临着我以前遇到的问题。你能用最新的代码更新你的帖子吗?我刚刚更新了,我看到了另一个问题:dns。lookup
立即返回,因为它的延续是在一个传递的回调中。也许最好将整个请求处理程序转换为异步并包装所有dns.lookup
调用具有新承诺的函数
。这样,代码将非常直接地工作,并且更像您计划的那样工作。