sql >> Databáze >  >> RDS >> Mysql

Nodejs vyjadřuje a slibuje, že neudělá to, co očekávám

Problémy s kódem

Dobře, je tu spousta problémů, takže nejdřív.

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

To nebude fungovat, protože vracíte data volajícímu, což je databázový dotaz, který volá zpětné volání s err a rows a nezajímá vás návratová hodnota vašeho zpětného volání.

Co musíte udělat, je zavolat nějakou jinou funkci nebo metodu, když máte řádky, nebo když ne.

Voláte:

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

a očekáváte, že tam dostanete řádky, ale nedostanete. To, co dostanete, je undefined a získáte to rychleji, než se spustí dotaz na databázi. Funguje to takto:

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 metoda se vrátí ihned poté, co předáte funkci, ještě před připojením k databázi. Po nějaké době se může zavolat funkce, kterou jste předali této metodě, ale bude to dlouho poté, co jste již vrátili undefined na kód, který chtěl hodnotu v:

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

Místo vracení hodnot ze zpětných volání z nich musíte volat některé další funkce nebo metody (například některá zpětná volání, která musíte volat, nebo metodu k vyřešení příslibu).

Vrácení hodnoty je synchronní koncept a nebude fungovat pro asynchronní kód.

Jak se mají používat sliby

Nyní, pokud vaše funkce vrátila slib :

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

pak jej budete moci použít v jiné části vašeho kódu takto:

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

Vysvětlení

Stručně řečeno, pokud spouštíte asynchronní operaci - jako je databázový dotaz - pak nemůžete mít hodnotu okamžitě takto:

var value = query();

protože server by musel zablokovat čekání na databázi, než by mohl provést přiřazení – a to se děje v každém jazyce se synchronním, blokujícím I/O (proto musíte mít vlákna v těchto jazycích, aby bylo možné hotovo, dokud je vlákno blokováno).

V Node můžete buď použít funkci zpětného volání, kterou předáte asynchronní funkci, aby byla volána, když má data:

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

Nebo můžete dostat slib:

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

Ale v obou případech otherCode() bude spuštěna ihned po registraci vašich obslužných funkcí zpětného volání nebo příslibu, než bude mít dotaz nějaká data – to znamená, že není třeba provádět žádné blokování.

Shrnutí

Celá myšlenka spočívá v tom, že v asynchronním, neblokujícím, jednovláknovém prostředí, jako je Node.JS, nikdy neděláte více věcí najednou – ale můžete čekat na spoustu věcí. Ale nemusíte jen na něco čekat a nic nedělat, zatímco čekáte, naplánujete si jiné věci, čekáte na další věci a nakonec vám zavolají zpět, až to bude připraveno.

Ve skutečnosti jsem pro ilustraci tohoto konceptu napsal krátký příběh na Medium:Nonblacking I/O na planetě Asynchronia256/16 – Povídka volně založená na nejistých faktech .




  1. Doctrine Query Language získat maximální/nejnovější řádek na skupinu

  2. Jak vytvořit řadová čísla v PostgreSQL

  3. Autonomní transakce v PostgreSQL 9.1

  4. Jak vypočítat marži v MySQL