最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - FIREBASE WARNING Can't set headers after they are sent - Stack Overflow

programmeradmin1浏览0评论

I would use data stream to update automatically my angular material datatable when data get pushed to the database

Here's my 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
      }

    );

  });

When I run my app I get all my data, then when I try to post data to the database I get this error :

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

When I use once instead of on I don't get error, but as I need to fetch for new data every update on database, I should use on to get a data stream.

So how can I use on without getting this error ?

I would use data stream to update automatically my angular material datatable when data get pushed to the database

Here's my 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
      }

    );

  });

When I run my app I get all my data, then when I try to post data to the database I get this error :

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

When I use once instead of on I don't get error, but as I need to fetch for new data every update on database, I should use on to get a data stream.

So how can I use on without getting this error ?

Share Improve this question edited Feb 22, 2018 at 23:55 Hamza Haddad asked Feb 22, 2018 at 23:51 Hamza HaddadHamza Haddad 1,5567 gold badges30 silver badges53 bronze badges 6
  • .on binds an handler that doesn't go away. .once binds a handler that goes away. Clearly you want the latter solution that you've proven works. – Kevin B Commented Feb 22, 2018 at 23:54
  • A single request can't respond more than once, therefore listening for more than just the next change makes no sense. – Kevin B Commented Feb 22, 2018 at 23:57
  • As the error is trying to tell you, you can only send a response once. – SLaks Commented Feb 22, 2018 at 23:57
  • once does not send an update to the front when new data is added – Hamza Haddad Commented Feb 22, 2018 at 23:57
  • you can't do that with an http request. – Kevin B Commented Feb 22, 2018 at 23:57
 |  Show 1 more ment

1 Answer 1

Reset to default 5

When you attach a listener with on("value"), it will keep listening for the data. This means that it will also fire if the data changes later, at which point you've long sent a response to the client and closed the socket.

To prevent this, you should listen with 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);
    });
  });

I also added a response to the error handler.

Update

If you want to keep sending updates to the client, you'll want to keep the connection open. In that case you shouldn't call res.send() (which closes the connection), but res.write() (which leaves the connection open). See 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);
    });
  });
发布评论

评论列表(0)

  1. 暂无评论