NodeJS response.render():发送后不能设置标头

时间:2018-04-12 17:38:32

标签: javascript node.js express

因此,第一次渲染成功app.get("/", function(request, response),但是当我处理app.post("/search", urlencodedParser, function(request, response)

我收到错误:

  

c:\ weather \ views \ main.hbs:发送后不能设置标题。

我看过The function res.render()should only be called once per request.,但我不明白 - 如果可以的话,如何使用views(Handlebars)更改数据?用新数据再次调用渲染?



var express = require("express");
var fs = require("fs");
var bodyParser = require("body-parser");
var hbs = require("hbs");
// create object
var app = express();
//urlEncoded
var urlencodedParser = bodyParser.urlencoded({
  extended: false
});
//read city.json
var content = fs.readFileSync("./city.list.json", "utf8");
var cities = JSON.parse(content);
//set view Handlebars
app.set("view engine", "hbs");
//register Helper - ResultBlock
hbs.registerHelper("ResultBlock", function(array) {
  var res = "";
  if (array[0] == "false") {
    res = '<div class="alert alert-warning alert-dismissible fade show"><button type="button" class="close" data-dismiss="alert">&times;</button><strong>Not Found!</strong> The ' + array[1] + ' is not correct.</div>';
  } else if (array[0] == "true") {
    res = 'Succsesful!!!';
  }
  return new hbs.SafeString(res);
})
app.get("/", function(request, response) {
  //response.sendfile('index.html');
  response.render("main.hbs", {
    city_value: "Zaporozhye",
    data: []
  })
});
app.post("/search", urlencodedParser, function(request, response) {
  var city = request.body.city;
  var idCity = -1;
  for (let i = 0; i < cities.length; i++) {
    if (cities[i].name == city) {
      idCity = cities[i].id;
      break;
    }
  }

  if (idCity != -1) {
    response.render("main.hbs", {
      city_value: city,
      data: ["true", city]
    })
  } else {
    response.render("main.hbs", {
      city_value: city,
      data: ["false", city]
    })
  }
  response.end();
});

app.listen(3000);
&#13;
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Document</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="app.js" type=""></script>
  <link rel="stylesheet" href="style.css">
  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">

  <!-- jQuery library -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <!-- Popper JS -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>

  <!-- Latest compiled JavaScript -->
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>

<body>
  <div class="container-fluid" style="background-color:black; color:darkorange;">
    <div class="row">
      <div class="col">
        <h1>Weather</h1>
      </div>
      <div class="col-*-*">
        <form action="/search" method="post">
          <div class="row">
            <div class="col">
              <input type="text" class="form-control" name="city" value="{{city_value}}" />
            </div>
            <div class="col">
              <button type="submit" class="btn btn-primary">Search</button>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
  <div id="result_block" class="container">
    {{ResultBlock data}}
  </div>
</body>

</html>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:2)

response.render是一个异步函数。因此,渲染是在当前执行上下文完成之后完成的。

在代码的最后,您调用response.end()并因此在渲染开始之前完成响应。

完成响应后,异步呈现函数将启动并尝试设置标题,但这是不可能的,因为响应已经完成,这就是您收到该错误的原因。

删除response.end(),一切都应该正常。

答案 1 :(得分:0)

你应该删除response.end()行,因为你使用了response.render

答案 2 :(得分:0)

函数response.end()用于发送响应的标头并结束响应过程。
另一方面,函数response.render()呈现视图,并且还发送标题并结束响应。
在同一个响应对象上调用两个将尝试为同一个请求发送两次头,这是不可能的,因为每个请求只能有一个响应。

<小时/> 因此,从&#39; / search&#39;的后期路由处理程序末尾删除response.end()应该解决问题。
更新了代码&#39; / search&#39; POST路由处理程序:

app.post("/search", urlencodedParser, function(request, response) {
  var city = request.body.city;
  var idCity = -1;
  for (let i = 0; i < cities.length; i++) {
    if (cities[i].name == city) {
      idCity = cities[i].id;
      break;
    }
  }

  if (idCity != -1) {
    response.render("main.hbs", {
      city_value: city,
      data: ["true", city]
    })
  } else {
    response.render("main.hbs", {
      city_value: city,
      data: ["false", city]
    })
  }
});