0

I am using express to render a page with some html that is built from information pulled from an eventEmitter.

Essentially the code right now is something like this:

app.post("/login", (req, res) => {
  let factory = eventFactory(args);
  let client = factory.client();
  let html;
  client.once(client.Event.Ready, function() {
                                            html = buildHTML(someArgs);
                                            res.render("page", {html: html});
                                            })
}

This draws it fine once. However, I'd like to have the page redraw upon new events. I know I could use client.on() for firing this callback upon each received event, however I don't believe just changing that will push anything down to the client.

I tried a simple http-meta tag for refreshes on the client side of the app but I get errors saying cannot GET /login when it refreshes.

So I think my design is probably incorrect here. Looking for tips and/or advice on how to approach or design this so that the client gets updated information upon an event received from the event handler. Is the only way to do this to use AJAX or websockets?

Thank You

Josh Klein
  • 305
  • 2
  • 8

1 Answers1

1

Web sockets would allow you to push new events to the client. With AJAX you would have to poll the server repeatedly, like with the http-meta tag. The error you get is because your first request is a POST, whereas refresh requests are GET requests and your server only supports POST (this can be fixed, of course).

Incidentally, if you don't mind incomplete HTML pages, you can use a different approach, using the fact that browsers display an HTML page even if the response has not yet finished. (Browsers report "timeout" after a while, but perhaps not if there is already something to display.)

The following code illustrates the idea. Every second, there is an event that increases a counter. This is written to the client as an HTML p element. They appear one below the other in this example, but using CSS you can change this so that they seem to "update" the page.

app.use(function(req, res) {
  var count = 0;
  res.write("<!DOCTYPE html><html><body>");
  setInterval(function() {
    res.write(`<p>${++count}</p>`);
  }, 1000);
});

A "progress indicator" could be implemented in this way.

Heiko Theißen
  • 12,807
  • 2
  • 7
  • 31
  • I'm intrigued by that solution you posted. Is there a way to 'destroy' or 'delete' HTML that's already on the page and replace it with what's coming through the event emitter? – Josh Klein Jan 19 '22 at 16:29
  • 1
    No, you can only add to the response. That's why CSS (e.g., absolute positioning of `p` elements) is needed to achieve the desired effect. – Heiko Theißen Jan 19 '22 at 16:32
  • Ok, so to do this by creating a get route I'd have to essentially duplicate my post route? It's interesting because just pressing the refresh button on the browser works, that must mean the browser is re-doing the post request upon refresh? – Josh Klein Jan 19 '22 at 16:40
  • 1
    Yes, duplicate it (give the `(req, res) => ...` function a name and use that in both, don't type it twice). And, yes the browser repeats a POST request (after a warning that this might buy you a second washing machine). – Heiko Theißen Jan 19 '22 at 16:44
  • thanks - for my purposes a refresh every 2 seconds is probably enough. I can explore websockets if that becomes a problem. – Josh Klein Jan 19 '22 at 19:38