sql >> Database >  >> RDS >> Mysql

Nodejs express en belooft niet te doen wat ik verwacht

Problemen met de code

Oké, er zijn hier veel problemen, dus de eerste dingen eerst.

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

Dit werkt niet omdat u gegevens terugstuurt naar de beller, de databasequery die uw callback oproept met err en rows en geeft niet om de retourwaarde van uw terugbelverzoek.

Wat je moet doen, is een andere functie of methode aanroepen als je de rijen hebt of niet.

U belt:

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

en je verwacht de rijen daar te krijgen, maar dat gebeurt niet. Wat je krijgt is undefined en u zult het sneller krijgen dan de databasequery zelfs maar is gestart. Het werkt als volgt:

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
}

De pool.getConnection methode retourneert onmiddellijk nadat u een functie hebt doorgegeven, zelfs voordat de verbinding met de database is gemaakt. Na enige tijd kan die functie die u aan die methode hebt doorgegeven, worden aangeroepen, maar het zal lang duren nadat u al undefined hebt geretourneerd naar de code die een waarde wilde in:

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

In plaats van waarden van callbacks terug te geven, moet je een aantal andere functies of methoden van hen aanroepen (zoals sommige callbacks die je moet aanroepen, of een methode om een ​​belofte op te lossen).

Het retourneren van een waarde is een synchroon concept en werkt niet voor asynchrone code.

Hoe beloften moeten worden gebruikt

Als uw functie nu een belofte heeft geretourneerd, :

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');
            }
        });
      });
    });
}

dan kun je het als volgt in een ander deel van je code gebruiken:

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);
        });
    });
    // ...

Uitleg

Samengevat, als u een asynchrone bewerking uitvoert, zoals een databasequery, kunt u de waarde niet meteen als volgt hebben:

var value = query();

omdat de server het wachten op de database zou moeten blokkeren voordat deze de opdracht kon uitvoeren - en dit is wat er gebeurt in elke taal met synchrone, blokkerende I/O (daarom moet je threads in die talen hebben zodat andere dingen kunnen worden gedaan terwijl die thread is geblokkeerd).

In Node kun je ofwel een callback-functie gebruiken die je doorgeeft aan de asynchrone functie om aangeroepen te worden wanneer deze gegevens heeft:

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

Of je kunt een belofte krijgen:

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

Maar in beide gevallen otherCode() wordt uitgevoerd onmiddellijk na het registreren van uw callback- of belofte-handlers, voordat de query gegevens bevat - dat wil zeggen dat er geen blokkering hoeft te worden uitgevoerd.

Samenvatting

Het hele idee is dat je in een asynchrone, niet-blokkerende, single-threaded omgeving zoals Node.JS nooit meer dan één ding tegelijk doet - maar je kunt op veel dingen wachten. Maar je wacht niet gewoon op iets en doet niets terwijl je wacht, je plant andere dingen, wacht op meer dingen en uiteindelijk word je teruggebeld als het klaar is.

Eigenlijk heb ik een kort verhaal op Medium geschreven om dat concept te illustreren:Niet-zwarte I/O op de planeet Asynchronia256/16 - Een kort verhaal losjes gebaseerd op onzekere feiten .




  1. Hoe age() werkt in PostgreSQL

  2. SQL Server Pre-Login Handshake-bevestigingsfout

  3. Hoe herstel ik een dumpbestand van mysqldump?

  4. mysql_fetch_row() versus mysql_fetch_assoc() versus mysql_fetch_array()