javascript - 快速路由触发 : "Can' t set headers after they are sent.“错误

标签 javascript node.js google-maps express ejs

我是 Express 新手,在从后端向前端发送数据时遇到问题。这是我想做的:我的主页上有一个 Google Map API (home.ejs)。 app.js 是服务器代码:当加载主页时,app.js 生成一些随机位置并发送到 home.ejs,因此home.ejs 使用这些位置作为标记。现在我想为每个标记添加一个事件监听器,以便当鼠标悬停在标记上时,它会向服务器发送 GET 请求,以请求显示图片。

我觉得来回发送请求/数据对我来说是一个很大的挑战。当鼠标悬停时,home.ejs/getImage/:num 路由发送 GET 请求,并 app.get("/getImage/:num ", function(req, res){}) 通过检索图像 url 来响应该请求,然后重定向到 "/" 并将 url 发送给它。这是我收到“发送后无法设置 header ”的地方。

我对 Express 和 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>

最佳答案

您误解了 redirect 的目的。 express 的redirect函数说:“这条路径没有答案;而是尝试向另一条路径发送请求,看看它说什么。” (这是通过像 3xx301 这样的 302 响应来完成的。)

您的困惑是您认为您需要告诉客户端哪个页面应该呈现给定的 URL。但这不是必需的:服务器不会告诉客户端如何呈现其发送的数据。服务器只发送数据,客户端决定如何处理它。

好消息是您的客户端 JavaScript 正在正确执行其工作。它使用 XMLHttpRequest从服务器获取数据。只需让服务器实际发送带有 send 的数据即可。函数并且调用 redirect 。一旦您的客户端有了要加载的 URL,您就可以将其加载到 <img> 中。元素与

var img = new Image();
img.src=responseText;
document.body.appendChild(img);

在你的onreadystatechange里面听众。您可以使用document.getElementById(...) 如果您不想将元​​素添加到 body 中,则获取不同的元素.

关于javascript - 快速路由触发 : "Can' t set headers after they are sent.“错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44375065/

相关文章:

javascript - 在 Javascript 中一次通过一组 4 个元素循环遍历数组?

javascript - Angular 7 : ngsw-worker. js加载失败

javascript - Node js 上的 if 条件

node.js - 我可以在 Powershell 的 PATH 中包含相对于当前目录的文件夹吗?

javascript - Google 路线在 Internet Explorer 9 和 10 中不显示 map

google-maps - 地点选择器已弃用

javascript - 更新 Vue.js 中的嵌套属性

node.js - 如何解析以数组作为输入的 GraphQl 突变

node.js - 如何从 Angular 向 Node 服务器发出发布请求

ios - swift - 如何在再次打开应用程序之前从上一个 session 中删除谷歌地图标记?