Home > Back-end >  Node Function Running Twice
Node Function Running Twice

Time:09-23

I am using a simple JS script to query a Postgres DB. I simply want to write a simple query to the webpage, but every time I think I'm calling the function, it calls twice

// query the db
rate = () => pool
    .query(rateQuery)
    .then(res => {return res.rows[0]})
    .catch(err => console.log('error: ', err.stack))

const app = http.createServer((request, response) => {
    // set response header
    response.writeHead(200, { 'Content-Type': 'text/html' });

    // get result of promise
    r = rate()
        .then(res => response.write(JSON.stringify(res), () => {console.log("DONE"); response.end()}))
        .catch(err => console.log('error: ', err.stack))
  });

  app.listen(3000);

When the page is refreshed, it prints DONE twice but I only want it once, any help is much appreciated - thanks.

CodePudding user response:

If you add console.log(request.url) in your request handler, you will likely see that that the second request is when the browser asks your server for the /favicon.ico that represents the site. Browsers do this. When a user types in a URL for a site and hits enter, the browser requests that URL from the target site and then it also asks for /favicon.ico if there wasn't a previously cached icon already for that site.

In general, you should not have an http request handler like this that pays no attention to the request URL path because then you will process anything that the browser or a search crawler or anything sends you. Instead, you should look for a specific URL path and only do your work when it's the desired path and return a 404 response for all other paths.

I'd suggest you change your request handler to this:

const app = http.createServer((request, response) => {
    // set response header
    if (request.url === "/") {

        // get result of promise
        rate().then(res => {
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.write(JSON.stringify(res), () => { 
                response.end();
                console.log("DONE");
            });
        }).catch(err => {
            console.log('error: ', err.stack);
            response.writeHead(500);
            response.end();
        });
    } else {
        response.writeHead(404, "unknown URL");
        response.end();
    }
});

Note: I change the content-type to text/plain. You had it as text/html, but you weren't sending html at all. You could perhaps make the content-type application/json, but in any case when you're sending JSON, it's not HTML.

This also incorporates cleaner error handling where all error paths send an error response.

P.S. Writing out this simple request handler using the plain http.createServer() request handler reminds me of how much simpler it is to use Express for request handler implementations. It handles so much of this for you while still giving you full control. It's lightweight and simpler.


FYI, here's the program written using Express:

const express = require('express');
const app = express();

app.get("/", (req, res) => {
      rate().then(res => {
          res.json(res);
      }).catch(err => {
          console.log(err);
          res.sendStatus(500);
      });
});

// if we get here, then no other request handler handled the incoming request
// so we send back a 404
app.use((req, res) => {
    res.sendStatus(404);
});

app.listen(3000);

CodePudding user response:

There is one possibility. rate already is a function which you defined as

// query the db
    rate = () => pool
                 .query(..........

Therefore, I don't think you would need parenthesis when you call it. Change from this

// get result of promise
        r = rate()
            .then .........

to this

// get result of promise
        r = rate
            .then .........
  • Related