表示路由触发器:“发送后无法设置标头。”错误
我是Express新手,无法将数据从后端发送到前端。这是我想要做的:我在主页上有一个Google Map API(home.ejs
)。 app.js
是服务器代码:当主页加载时,app.js
生成一些随机位置并发送到home.ejs
,因此home.ejs
使用这些位置作为标记。现在我想为每个这些标记添加一个事件监听器,这样当鼠标悬停在标记上时,它会向服务器发送一个GET请求,以请求显示一张图片。表示路由触发器:“发送后无法设置标头。”错误
我觉得来回发送请求/数据是一个很大的挑战。当鼠标结束时,home.ejs
发送GET请求到/getImage/:num
路由,并且app.get("/getImage/:num", function(req, res){})
通过检索图像url来响应该请求,并重定向到"/"
,并将URL发送给它。这是我得到的“Can't set headers after they are sent"
。
我很新的表达与EJS,我甚至不知道我是否在正确的轨道上。我应该如何实现这个经过?
获得通信这是app.js
服务器文件
var express = require("express");
var app = express();
//app.use(express.static(__dirname + "/public"));
app.use(express.static(__dirname));
app.set("view engine","ejs");
var lng_min = -84.161;
var lng_max = -83.688;
var lat_min = 35.849;
var lat_max = 36.067;
var urls = [
"http://cdn1-www.dogtime.com/assets/uploads/2015/01/file_21032_the-most-popular-dog-and-cat-names.jpg",
"http://qltyctrl.com/wp-content/uploads/2014/03/Sad-Dog-and-Cat.jpg",
"https://blog-photos.dogvacay.com/blog/wp-content/uploads/2015/07/dog-cat-smarter-ftr.jpg",
"http://qltyctrl.com/wp-content/uploads/2014/03/Dog-and-Cat-on-a-Log.jpg",
"http://images.boomsbeat.com/data/images/full/31730/cat-and-dog_1-jpg.jpg",
"http://www.vetlocator.com/dailypaws/wp-content/uploads/2012/04/dog-cat2.jpg",
"http://qltyctrl.com/wp-content/uploads/2014/03/Old-Dog-and-Cat-Sleepy-Embrace.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQXNMdvNfc3WYMqbPrJrnjgHJRp2zB1y9vx545LfO-_U5_yvgBo",
"http://www.vetlocator.com/dailypaws/wp-content/uploads/2012/04/dog-cat8.jpg",
"http://www.maddiesfund.org/assets/metaImage/robust-dog-cat-foster.jpg"
]
var numLocations = 10;
var data = [];
function generateData() {
// generate random locations and the url to download pictures
for (var i = 0; i < numLocations; ++i) {
var lng = Math.random() * (lng_max - lng_min) + lng_min;
var lat = Math.random() * (lat_max - lat_min) + lat_min;
var tuple = {
id: i,
lng: lng,
lat: lat,
pic: urls[i]
};
data.push(tuple);
}
}
app.get("/", function(req, res) {
//res.send("Hello it works");
data = [];
generateData();
res.render("home.ejs", {data: data});
});
app.get("/getImg/:num", function(req, res) {
console.log(req.params.num);
var i = Number(req.params.num);
res.redirect("/");
res.send({imgUrl: data[i].pic});
});
app.listen(process.env.PORT, process.env.IP, function() {
console.log("Server Started!");
});
home.ejs
文件:
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<link rel="stylesheet" type="text/css" href="/public/app.css">
</head>
<body>
<div id="map">
</div>
<script>
var data = <%- JSON.stringify(data) %>;
console.log(data.length);
function initMap() {
var loc = {lat: 35.9606, lng: -83.9207};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: loc
});
for (var i = 0; i < data.length; ++i) {
var loc = {lat: data[i].lat, lng: data[i].lng};
var marker = new google.maps.Marker({
position: loc,
map: map
// id: i
});
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, 'mouseover', (function(marker) {
return function() {
// var content = '<div id="imgDisplay">'
// + '<img src="http://www.maddiesfund.org/assets/metaImage/robust-dog-cat-foster.jpg">'
// + '</div>';
// infowindow.setContent(content);
// infowindow.open(map, marker);
var xhr = new XMLHttpRequest();
var params = 3;
xhr.open('GET','/getImg/'+params, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(responseText);
}
}
//xhr.send(params);
xhr.send();
}
})(marker));
}
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAOwfkV_GbUXyH2s8iD0gS6pje9J3R96dM&callback=initMap">
</script>
</body>
</html>
你误解的0123宗旨。 Express的redirect
函数说:“这条路径没有答案,而是尝试向其他路径发送请求,看看它说了什么。” (这是通过3xx
响应完成的,如301
或302
。)
您的困惑是,您认为您需要告诉客户端哪个页面应呈现给定的URL。但这不是必需的:服务器不会告诉客户端如何呈现它发送的数据。服务器只是发送数据,客户端决定如何处理它。
好消息是您的客户端JavaScript正在正确地完成其工作。它使用XMLHttpRequest
从服务器获取数据。只需要服务器实际发送该数据与send
函数和不要调用redirect
。一旦您的客户端有要加载的URL,您可以在<img>
元素与
var img = new Image();
img.src=responseText;
document.body.appendChild(img);
您onreadystatechange
监听器里加载它。如果您不想将元素添加到您的body
,则可以使用document.getElementById(...)
获取不同的元素。
非常感谢你的帮助,并向我解释了这个概念!我刚刚得到它的工作。 – daydayup
我不明白你的意思,“app.js通过检索图片url来响应该请求,并重定向到”/“'并将url发送给它。”读完这些后,我不明白你想要发生什么。你可以使用'redirect'重定向到另一个路径,'redirect'发送一个'3xx' HTTP响应(此时该路径的处理程序将运行)*或*可以通过发送'2xx'响应的'send'发送数据。这些是互斥的 - 要么是响应是重定向响应还是数据响应。在请求到/ getImg后,你想让顶层页面重定向到'/'吗? – apsillers
对此感到抱歉。 Google地图位于首页(“/”)。当我发送GET请求时,它被发送到“/ getImg /:num”。应用程序。get(“/ getImg /:num”)响应GET请求并从数据矩阵中提取图像URL,但我希望它重定向到“/”,以便我可以在主页上显示图像(“/”) – daydayup
好的,我认为这里的答案是:你对'重定向(“/”)做什么的理解是错误的。 'redirect(“/”)'发送一个'3xx'(可能是'301'或'302')HTTP响应并且说:“我没有给你答案;相反,尝试从路径加载数据'/' “。但是你不想这么做 - 你已经有了这些数据并准备发送它!相反,我想你要做的就是从'urls'数组发送URL,然后在客户端执行'img = new Image(); img.src = responseText的; document.body.appendChild(IMG)'。是对的吗? – apsillers