sql >> Database teknologi >  >> RDS >> Mysql

Nodejs udtrykker og lover ikke at gøre, hvad jeg forventer

Problemer med koden

Ok, der er mange problemer her, så først til kende.

        connection.query('...', function (err, rows) {
            connection.release();
            if (!err) {
                return rows;
            } else {
                return false;
            }
        });

Dette vil ikke fungere, fordi du returnerer data til den, der ringer, som er databaseforespørgslen, der kalder dit tilbagekald med err og rows og er ligeglad med returværdien af ​​dit tilbagekald.

Det du skal gøre er at kalde en anden funktion eller metode, når du har rækkerne, eller når du ikke har det.

Du ringer til:

var rows = loginM.findUser(req.body, res);

og du forventer at få rækkerne der, men det vil du ikke. Det du får er undefined og du får det hurtigere, end databaseforespørgslen overhovedet er startet. Det fungerer sådan her:

me.findUser = function(params, res) {
    // (1) you save the username in a variable
    var username = params.username;

    // (2) you pass a function to getConnection method
    pool.getConnection(function (err, connection) {
        console.log("Connection ");

        if (err) {
            console.log("ERROR 1 ");
            res.send({"code": 100, "status": "Error in connection database"});
            return;
        }

        connection.query('select Id, Name, Password from Users ' +
            'where Users.Name = ?', [username], function (err, rows) {
            connection.release();
            if (!err) {
                return rows;
            } else {
                return false;
            }
        });

        //connection.on('error', function (err) {
        //    res.send({"code": 100, "status": "Error in connection database"});
        //    return;
        //});
    });

    // (3) you end a function and implicitly return undefined
}

pool.getConnection metoden returnerer umiddelbart efter du har sendt en funktion, før forbindelsen til databasen overhovedet er oprettet. Så, efter et stykke tid, kan den funktion, som du har videregivet til den metode, blive kaldt, men det vil vare længe efter, at du allerede har returneret undefined til koden, der ønskede en værdi i:

var rows = loginM.findUser(req.body, res);

I stedet for at returnere værdier fra tilbagekald, skal du kalde nogle andre funktioner eller metoder fra dem (som nogle tilbagekald, du skal kalde, eller en metode til at løse et løfte).

At returnere en værdi er et synkront koncept og vil ikke fungere for asynkron kode.

Hvordan løfter skal bruges

Nu, hvis din funktion returnerede et løfte :

me.findUser = function(params, res) {
    var username = params.username;

    return new Promise(function (res, rej) {

      pool.getConnection(function (err, connection) {
        console.log("Connection ");

        if (err) {
          rej('db error');
        } else {
          connection.query('...', [username], function (err, rows) {
            connection.release();
            if (!err) {
                res(rows);
            } else {
                rej('other error');
            }
        });
      });
    });
}

så vil du være i stand til at bruge den i en anden del af din kode på en måde som denne:

app.post('/login/', function(req, res, next) {

    var promise = new Promise(function (resolve, reject) {

        // rows is a promise now:
        var rows = loginM.findUser(req.body, res);

        rows.then(function (rowsValue) {
            console.log("Success");
            resolve(rowsValue);
        }).catch(function (err) {
            console.log("Failed");
            reject(err);
        });
    });
    // ...

Forklaring

Sammenfattende, hvis du kører en asynkron operation - som en databaseforespørgsel - så kan du ikke umiddelbart have værdien sådan:

var value = query();

fordi serveren skulle blokere for at vente på databasen, før den kunne udføre opgaven - og det er hvad der sker på alle sprog med synkron, blokerende I/O (det er derfor du skal have tråde på de sprog, så andre ting kan gjort, mens tråden er blokeret).

I Node kan du enten bruge en tilbagekaldsfunktion, som du overfører til den asynkrone funktion for at blive kaldt, når den har data:

query(function (error, data) {
  if (error) {
    // we have error
  } else {
    // we have data
  }
});
otherCode();

Eller du kan få et løfte:

var promise = query();
promise.then(function (data) {
  // we have data
}).catch(function (error) {
  // we have error
});
otherCode();

Men i begge tilfælde otherCode() vil blive kørt umiddelbart efter registrering af dine tilbagekalds- eller løftehandlere, før forespørgslen har nogen data - det betyder, at ingen blokering skal foretages.

Oversigt

Hele ideen er, at i et asynkront, ikke-blokerende, enkelttrådsmiljø som Node.JS laver man aldrig mere end én ting ad gangen – men man kan vente på mange ting. Men du venter ikke bare på noget og laver ingenting, mens du venter, du planlægger andre ting, venter på flere ting, og til sidst bliver du ringet tilbage, når det er klar.

Faktisk skrev jeg en novelle på Medium for at illustrere det koncept:I/O ikke-sort på planeten Asynchronia256/16 - En novelle løst baseret på usikre fakta .




  1. Forespørgsel for at søge i alle pakker efter tabel og/eller kolonne

  2. Hvordan tester jeg i WiX for eksistensen af ​​en registreringsnøgle (ikke værdi) til Oracle ODP.Net

  3. Sådan opretter du en krydstabuleringsforespørgsel i designvisning i Access

  4. SQLite JSON_EXTRACT()