0

I am retriving data from a DB. I am using promise to return the data back to the client when the data is ready:

var http = require('http');
var mysql = require('mysql');


var con = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "******",
  database: "heroes"
});



let myPromise = new Promise(function(myResolve, myReject) {
    con.connect(function(err) {
      if (err) throw err;
      con.query("SELECT id, name FROM heroes", function (err, result, fields) {
        if (err) throw err;
        console.log(result);
        myResolve(JSON.stringify(result));
      });
    });
});




http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});

  myPromise.then(result => res.end(result))
   
    
  
}).listen(8080);

I have learned that you are supposed to supply two call-back functions to the Promise and that these are optional arguments in case of success or failure.

When I am calling myResolve() (which doesn't exist in this case), the data is being sent back to the client fine using .then(). Nonetheless, when I am not calling myResolve() something doesn't work and the page is being refreshed forever.

A. If these are indeed callbacks, how can I call a non exsiting function such as myResolve() ? Why I can't extract result without calling this function ?

B. How can I execute the database query only after there is a request on the 8080 port ? When I am trying to insert the promise into a function, I can't use .then (I am assuming the function by itself doesn't have any promise to give obiously).

Code Edit for the second question:

function connectToDB()
{
    let myResult;
    
    let myPromise = new Promise(function(myResolve, myReject) {
        con.connect(function(err) {
          if (err) throw err;
          con.query("SELECT id, name FROM heroes", function (err, result, fields) {
            if (err) throw err;
            console.log(result);
            myResolve(JSON.stringify(result));
            myResult = result;
          });
        });
    });
    
    return myResult;
}

Final code edit after wraping the promise with a function:

function connectToDB()
{

    
    let myPromise = new Promise(function(myResolve, myReject) {
        con.connect(function(err) {
          if (err) throw err;
          con.query("SELECT id, name FROM heroes", function (err, result, fields) {
            if (err) throw err;
            console.log(result);
            myResolve(JSON.stringify(result));

          });
        });
    });
    
    return myPromise;
}

Edit:

The questions are still valid, regardless of the use of res.send or res.end, as far as I understand it has got nothing to do with what I am asking about.

RT.
  • 423
  • 3
  • 12
  • 2
    "*When I am calling `myResolve()` (which doesn't exist in this case)*" - what do you mean? Certainly the function exists, the promise constructor gave it to you. – Bergi Jul 08 '21 at 21:13
  • Instead of `if (err) throw err;`, you should most definitely use `if (err) myReject(err); else` – Bergi Jul 08 '21 at 21:14
  • "*When I am trying to insert the promise into a function, I can't use `.then`*" - yes you can. Please show us how you tried to use a function. [The function should `return` the promise](https://stackoverflow.com/a/25756564/1048572) so that the caller can call the `.then()` method of the result. – Bergi Jul 08 '21 at 21:15
  • @Bergi Maybe I am totaly off, but I am trying to understand. Isn't it a function name that I pass to the bigger function that I defined inside the promise in the constructor call ? Or do you mean that the constructor create this function using the name I supplied ("myResolve")? – RT. Jul 08 '21 at 21:16
  • @RT. Yes, the constructor does create this function, and passes it as an argument to the function you supplied. How you name the parameters of your function doesn't matter. – Bergi Jul 08 '21 at 21:22
  • @Bergi so I pass the name and the constructor creates this function based on the name I give it ? – RT. Jul 08 '21 at 21:23
  • @RT. You're not passing a name. You're passing a function with parameters. The constructor doesn't even care at all if your function has declared parameters or not, it always passes the `resolve` and `reject` function as first and second argument to your function. – Bergi Jul 08 '21 at 21:26
  • @Bergi than what is the purpose of resolve and reject ? I am always using a parameter called "result" to extract the data. – RT. Jul 08 '21 at 21:29
  • @RT. Let's clarify if you understand how function parameters work. If I have a function defined as `foo (x) { ... }` and you call it as `var a=10; foo(a)` do you think I am creating a number with the name `x` from my `a` variable with the value of `10`? – slebetman Jul 08 '21 at 21:32
  • @RT. They provide you with the ability to resolve and reject the promise respectively (and you are strongly advised to do that, although nothing stops you from not using/calling these functions). Not sure what you mean by "extract"? – Bergi Jul 08 '21 at 21:33
  • @slebetman you are creating a copy of that variable which will hold the same value. – RT. Jul 08 '21 at 21:38
  • @Bergi Ok I think I understand, than if I am not calling this function, I will not be able to use the result value from the promise ? – RT. Jul 08 '21 at 21:39
  • @RT. If you're not resolving the promise, the promise won't have a result value. – Bergi Jul 08 '21 at 21:41
  • @Bergi Ok, thanks. As for the second question, I have edited with what I tried to do in order to call a function for each request. – RT. Jul 08 '21 at 21:55
  • @RT. Correct. Now, if I have a function defined as `foo (x) { .. }` and you call it as `function a () { .. }; foo(a)` you can understand that you are not "creating this function using the name you supplied". You are just passing a function as a variable to `foo()`. That's what the Promise object does. It calls your function by passing a function as argument. Just like the number `10` what YOU name the function argument and what I name my variable does not have to match. – slebetman Jul 08 '21 at 21:56
  • @RT. Remove that `myResult`, [that approach won't work](https://stackoverflow.com/q/23667086/1048572). Just keep the original code of your promise, wrap it in a function declaration, and `return myPromise`. Yes, this returns the promise object (that will fulfill with the result), not the result itself (which is impossible). Your HTTP handler will then do `connectToDB().then(…)` instead of `myPromise.then(…)`. – Bergi Jul 08 '21 at 21:57
  • One thing you need to realize is that Promises is not part of javascript syntax. It is just a design pattern. you can write your own Promise system (as people did before promises became a standard part of the javascript standard library) – slebetman Jul 08 '21 at 22:00
  • @Bergi it works once but then I get : 'Error: Cannot enqueue Handshake after already enqueuing a Handshake.' – RT. Jul 08 '21 at 22:05
  • @Bergi , slebetman - Thanks. – RT. Jul 08 '21 at 23:29

1 Answers1

1

To answer these questions in order:

  1. The function 'myResolve' does exist, as it is being passed in when you create the promise: "new Promise(function(myResolve, myReject))". In this code, you are constructing a Promise object and passing a callback function into the constructor. The two parameters in this callback function are themselves callback functions which you are naming 'myResolve' and 'myReject'. Generally, people name them 'resolve' and 'reject', but the name does not matter as long as it is consistent throughout. Functions can be passed through functions just the same as strings and other types of variables.
  2. Right now, you are immediately declaring the 'myPromise' variable. You can defer the query until a request is hit by wrapping the 'myPromise' in a function which returns 'myPromise'. Then, when the request is made, call the new 'myPromiseFunction'.
byte-this
  • 204
  • 1
  • 2
  • about 2, it works once but then I get : 'Error: Cannot enqueue Handshake after already enqueuing a Handshake' – RT. Jul 08 '21 at 23:19
  • It sounds like you might need to close the connection or reuse an existing connection after it has been created. I'm not too familiar with that library but that is what the error message sounds like. – byte-this Jul 08 '21 at 23:20
  • Thanks I searched for the error and it seems like you don't need to call 'con.connect' if you already created a connection using 'createConnection': https://stackoverflow.com/questions/14087924/cannot-enqueue-handshake-after-invoking-quit – RT. Jul 08 '21 at 23:28
  • I need to note that it seems like the accepted answer in the link I provided is not correct for a long term use according to other comments there. So for other readers sake, be aware... – RT. Jul 08 '21 at 23:36