【问题标题】:FIREBASE WARNING Can't set headers after they are sentFIREBASE WARNING 发送后无法设置标头
【发布时间】:2018-02-22 23:51:50
【问题描述】:

当数据被推送到数据库时,我会使用数据流自动更新我的角度材料数据表

这是我的 router.js

router
  .route("/")
  .get(function (req, res, err) {

    // Get a database reference to our posts
    var db = admin.database();
    var ref = db.ref("/");

    // Attach an asynchronous callback to read the data at our posts reference
    ref.on("value", function (snapshot) {
      var list = [];
      snapshot.forEach(function (elem) {
        list.push(elem.val());
      })


      res.send(list);

    }, function (errorObject) {
      console.log("The read failed: " + errorObject.code);
    });
  });

router
  .route("/")
  .post(function (req, res, err) {
    console.log(req.body);
    // Get a database reference to our posts
    var db = admin.database();
    var ref = db.ref("/");

    // Attach an asynchronous callback to read the data at our posts reference
    ref.push(
      {
        "text": req.body.text
      }

    );

  });

当我运行我的应用程序时,我得到了所有数据,然后当我尝试将数据发布到数据库时,我得到了这个错误:

FIREBASE WARNING: Exception was thrown by user callback. Error: Can't set headers after they are sent.

当我使用once 而不是on 时,我没有收到错误,但由于我需要在每次更新数据库时获取新数据,我应该使用on 来获取数据流。

那么如何使用on 而不出现此错误?

【问题讨论】:

  • .on 绑定一个不会消失的处理程序。 .once 绑定一个消失的处理程序。显然,您想要后一种您已证明有效的解决方案。
  • 一个请求不能多次响应,因此监听下一个变化是没有意义的。
  • 因为错误试图告诉你,你只能发送一次响应。
  • 有一次在添加新数据时不发送更新到前台
  • 你不能通过 http 请求来做到这一点。

标签: javascript node.js firebase express


【解决方案1】:

当您使用on("value") 附加侦听器时,它将继续侦听数据。这意味着如果数据稍后发生更改,它也会触发,此时您已经向客户端发送了响应并关闭了套接字。

为防止这种情况,您应该使用once("value") 收听:

router
  .route("/")
  .get(function (req, res, err) {

    // Get a database reference to our posts
    var db = admin.database();
    var ref = db.ref("/");

    // Attach an asynchronous callback to read the data at our posts reference
    ref.once("value", function (snapshot) {
      var list = [];
      snapshot.forEach(function (elem) {
        list.push(elem.val());
      })

      res.send(list);

    }, function (errorObject) {
      console.log("The read failed: " + errorObject.code);
      res.status(500).send(errorObject.code);
    });
  });

我还添加了对错误处理程序的响应。

更新

如果您想继续向客户端发送更新,您需要保持连接打开。在这种情况下,您不应该调用res.send()(关闭连接),而是调用res.write()(保持连接打开)。见Difference between response.send and response.write in node js

router
  .route("/")
  .get(function (req, res, err) {

    // Get a database reference to our posts
    var db = admin.database();
    var ref = db.ref("/");

    // Attach an asynchronous callback to read the data at our posts reference
    ref.on("value", function (snapshot) {
      var list = [];
      snapshot.forEach(function (elem) {
        list.push(elem.val());
      })


      res.write(list);

    }, function (errorObject) {
      console.log("The read failed: " + errorObject.code);
      res.status(500).send(errorObject.code);
    });
  });

【讨论】:

  • 正如我所说,不会创建数据流。我的意思是在前端我有一个监听我的 get http 请求。我希望当我在数据库中发布数据时,我的 observable 会自动更新视图。一次是不可能的。
  • 调用send() 会在写入后关闭连接。要保持连接打开,请使用write()。但一般来说,对于这种方法,请考虑使用 Web Sockets 而不是普通的 HTTP。
  • 现在我在写FIREBASE WARNING: Exception was thrown by user callback. TypeError: First argument must be a string or Buffer时得到这个错误
  • 我猜这意味着你只能写res.write(JSON.stringify(list))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 2013-04-06
  • 1970-01-01
  • 2015-12-20
相关资源
最近更新 更多