webentwicklung-frage-antwort-db.com.de

Versprechen Sie, um den MySQL-Rückgabewert in node.js zu verarbeiten

Ich habe einen Python-Hintergrund und migriert derzeit zu node.js. Ich habe Probleme mit der Anpassung an node.js aufgrund seiner asynchronen Natur.

Zum Beispiel versuche ich, einen Wert aus einer MySQL-Funktion zurückzugeben. 

function getLastRecord(name)
{
    var connection = getMySQL_connection();

    var query_str =
    "SELECT name, " +
    "FROM records " +   
    "WHERE (name = ?) " +
    "LIMIT 1 ";

    var query_var = [name];

    var query = connection.query(query_str, query_var, function (err, rows, fields) {
        //if (err) throw err;
        if (err) {
            //throw err;
            console.log(err);
            logger.info(err);
        }
        else {
            //console.log(rows);
            return rows;
        }
    }); //var query = connection.query(query_str, function (err, rows, fields) {
}

var rows = getLastRecord('name_record');

console.log(rows);

Nach einiger Lektüre stelle ich fest, dass der obige Code nicht funktionieren kann, und ich muss aufgrund der asynchronen Natur von node.js ein Versprechen zurückgeben. Ich kann node.js-Code nicht wie Python schreiben. Wie konvertiere ich getLastRecord(), um ein Versprechen zurückzugeben, und wie gehe ich mit dem zurückgegebenen Wert um?

In der Tat möchte ich so etwas tun;

if (getLastRecord() > 20)
{
    console.log("action");
}

Wie kann das in node.js lesbar gemacht werden? 

Ich würde gerne sehen, wie Versprechen in diesem Fall mit Bluebird umgesetzt werden können.

20
user781486

Ich habe Ihren Code geändert, um Q (NPM-Modul) Versprechen zu verwenden . Ich gehe davon aus, dass Ihre 'getLastRecord ()' - Funktion, die Sie im obigen Snippet angegeben haben, korrekt funktioniert.

Sie können den folgenden Link verwenden, um das Q-Modul zu erhalten

Hier klicken: Q Dokumentation

var q = require('q');

function getLastRecord(name)
{

var deferred = q.defer(); // Use Q 
var connection = getMySQL_connection();

var query_str =
"SELECT name, " +
"FROM records " +   
"WHERE (name = ?) " +
"LIMIT 1 ";

var query_var = [name];

var query = connection.query(query_str, query_var, function (err, rows, fields) {
    //if (err) throw err;
    if (err) {
        //throw err;           
        deferred.reject(err);
    }
    else {
        //console.log(rows);           
        deferred.resolve(rows);
    }
}); //var query = connection.query(query_str, function (err, rows, fields) {

return deferred.promise;
}



// Call the method like this
getLastRecord('name_record')
 .then(function(rows){
   // This function get called, when success
   console.log(rows);
  },function(error){
   // This function get called, when error
   console.log(error);

 });
7
Piyush Sagar

Ich bin neu bei Node.js und verspricht. Ich suchte eine Zeit lang nach etwas, das meinen Bedürfnissen entspricht, und das war es, worauf ich letztendlich zurückließ, nachdem ich einige Beispiele zusammengestellt hatte. Ich wollte die Möglichkeit, eine Verbindung per Abfrage zu erwerben und sie sofort nach Abschluss der Abfrage freizugeben (querySql), oder eine Verbindung aus dem Pool zu erhalten und sie innerhalb des Bereichs Promise. using zu verwenden oder sie immer wieder freizugeben (getSqlConnection) __. Mit dieser Methode können Sie mehrere Abfragen hintereinander zusammenstellen, ohne sie zu verschachteln.

db.js

var mysql = require('mysql');
var Promise = require("bluebird");

Promise.promisifyAll(mysql);
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);

var pool = mysql.createPool({
    Host: 'my_aws_Host',
    port: '3306',
    user: 'my_user',
    password: 'my_password',
    database: 'db_name'
});

function getSqlConnection() {
    return pool.getConnectionAsync().disposer(function (connection) {
        console.log("Releasing connection back to pool")
        connection.release();
    });
}

function querySql (query, params) {
    return Promise.using(getSqlConnection(), function (connection) {
        console.log("Got connection from pool");
        if (typeof params !== 'undefined'){
            return connection.queryAsync(query, params);
        } else {
            return connection.queryAsync(query);
        }
    });
};

module.exports = {
    getSqlConnection : getSqlConnection,
    querySql : querySql
};

usage_route.js

var express = require('express');
var router = express.Router();

var dateFormat = require('dateformat');
var db = require('../my_modules/db');
var getSqlConnection = db.getSqlConnection;
var querySql = db.querySql;

var Promise = require("bluebird");

function retrieveUser(token) {
  var userQuery = "select id, email from users where token = ?";
  return querySql(userQuery, [token])
     .then(function(rows){
        if (rows.length == 0) {
          return Promise.reject("did not find user");
        }

        var user = rows[0];
        return user;
     });
}

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

  Promise.resolve().then(function () {
    return retrieveUser(req.body.token);
  })
    .then(function (user){
      email = user.email;
      res.status(200).json({ "code": 0, "message": "success", "email": email});
    })
    .catch(function (err) {
      console.error("got error: " + err);
      if (err instanceof Error) {
        res.status(400).send("General error");
      } else {
        res.status(200).json({ "code": 1000, "message": err });
      }
    });
});

module.exports = router;
6
MikeL

Um Ihre erste Frage zu beantworten: Wie kann das in node.js lesbar gemacht werden?

Es gibt eine Bibliothek namens co , mit der Sie in einem synchronen Workflow asynchronen Code schreiben können. Einfach nachschauen und npm install co.

Das Problem, dem Sie bei diesem Ansatz sehr oft gegenüberstehen, ist, dass Sie Promise nicht aus allen Bibliotheken zurückbekommen, die Sie verwenden möchten. Sie haben es also entweder selbst verpackt (siehe Antwort von @Joshua Holbrook) oder suchen Sie nach einem Wrapper (zum Beispiel: npm install mysql-promise)

(Übrigens: Es steht auf der Roadmap für ES7, dass diese Art von Workflow mit den Schlüsselwörtern asyncawait nativ unterstützt wird, aber noch nicht im Knoten: Knoten Feature-Liste .)

3
CFrei

Sie müssen keine Versprechungen verwenden, Sie können eine Rückruffunktion verwenden.

function getLastRecord(name, next)
{
    var connection = getMySQL_connection();

    var query_str =
    "SELECT name, " +
    "FROM records " +    
    "LIMIT 1 ";

    var query_var = [name];

    var query = connection.query(query_str, query_var, function (err, rows, fields) {
        //if (err) throw err;
        if (err) {
            //throw err;
            console.log(err);
            logger.info(err);
            next(err);
        }
        else {
            //console.log(rows);
            next(null, rows);
        }
    }); //var query = connection.query(query_str, function (err, rows, fields) {
}

getLastRecord('name_record', function(err, data) {
   if(err) {
      // handle the error
   } else {
      // handle your data

   }
});
3
Jordi Ruiz

Dies kann beispielsweise mit Bluebird ganz einfach erreicht werden, wie Sie gefragt haben:

var Promise = require('bluebird');

function getLastRecord(name)
{
    return new Promise(function(resolve, reject){
        var connection = getMySQL_connection();

        var query_str =
            "SELECT name, " +
            "FROM records " +
            "WHERE (name = ?) " +
            "LIMIT 1 ";

        var query_var = [name];

        var query = connection.query(query_str, query_var, function (err, rows, fields) {
            //if (err) throw err;
            if (err) {
                //throw err;
                console.log(err);
                logger.info(err);
                reject(err);
            }
            else {
                resolve(rows);
                //console.log(rows);
            }
        }); //var query = connection.query(query_str, function (err, rows, fields) {
    });
}


getLastRecord('name_record')
    .then(function(rows){
        if (rows > 20) {
            console.log("action");
        }
    })
    .error(function(e){console.log("Error handler " + e)})
    .catch(function(e){console.log("Catch handler " + e)});
2
Andrej Burcev

Ich bin noch ein bisschen neu in Node, also habe ich vielleicht etwas verpasst, lass mich wissen, wie es funktioniert. Anstatt einen asynchronen Knoten auszulösen, wird er Ihnen nur aufgezwungen, sodass Sie vorausdenken und ihn planen müssen.

const mysql = require('mysql');
const db = mysql.createConnection({
          Host: 'localhost', 
          user: 'user', password: 'password', 
          database: 'database',
      });
      db.connect((err) => {
          // you should probably add reject instead of throwing error
          // reject(new Error()); 
          if(err){throw err;}
          console.log('Mysql: Connected');
      });
      db.promise = (sql) => {
          return new Promise((resolve, reject) => {
              db.query(sql, (err, result) => {
                if(err){reject(new Error());}
                else{resolve(result);}
              });
          });
      };

Hier benutze ich das mysql-Modul wie gewohnt, aber stattdessen habe ich eine neue Funktion erstellt, um das Versprechen im Voraus zu handhaben, indem ich es der db const hinzufüge. (Sie sehen dies in vielen Knotenbeispielen als "Verbindung".

Rufen wir nun eine MySQL-Abfrage mit dem Versprechen auf.

      db.promise("SELECT * FROM users WHERE username='john doe' LIMIT 1;")
      .then((result)=>{
          console.log(result);
      }).catch((err)=>{
          console.log(err);
      });

Ich habe festgestellt, dass dies nützlich ist, wenn Sie eine zweite Abfrage basierend auf der ersten Abfrage durchführen müssen.

      db.promise("SELECT * FROM users WHERE username='john doe' LIMIT 1;")
      .then((result)=>{
          console.log(result);
          var sql = "SELECT * FROM friends WHERE username='";
              sql = result[0];
              sql = "';"
          return db.promise(sql);
      }).then((result)=>{
          console.log(result);
      }).catch((err)=>{
          console.log(err);
      });

Sie sollten eigentlich die mysql-Variablen verwenden, aber dies sollte Ihnen zumindest ein Beispiel für die Verwendung von Versprechungen mit dem mysql-Modul geben.

Mit den oben genannten Funktionen können Sie die db.query auch weiterhin wie gewohnt verwenden, wenn Sie diese Versprechen einhalten. Sie funktionieren wie gewohnt.

Hoffe, das hilft beim Dreieck des Todes.

1
Dillon Burnett

Mit dem Paket promise-mysql besteht die Logik darin, die Versprechungen mithilfe von then (Funktion (Antwort) {Ihr Code}) zu verketten.

und 

catch (Funktion (Antwort) {Ihr Code}), um Fehler aus den "Then" -Blocks vor dem Catch-Block abzufangen.

Nach dieser Logik übergeben Sie Abfrageergebnisse in Objekten oder Arrays mit return am Ende des Blocks. Die Rückgabe hilft, die Abfrageergebnisse an den nächsten Block zu übergeben. Dann wird das Ergebnis im Funktionsargument gefunden (hier ist es test1). Mit dieser Logik können Sie mehrere MySql-Abfragen und den Code, der zum Manipulieren des Ergebnisses und zum Ausführen des gewünschten Befehls erforderlich ist, verketten. 

das Connection-Objekt wird so erstellt, dass es global ist, da jedes Objekt und jede Variable, die in jedem Block erstellt werden, nur lokal sind. Vergiss nicht, dass du mehr "dann" Blöcke verketten kannst.

var config = {
    Host     : 'Host',
    user     : 'user',
    password : 'pass',
    database : 'database',

  };
  var mysql = require('promise-mysql');
  var connection;
  let thename =""; // which can also be an argument if you embed this code in a function

  mysql.createConnection(config
  ).then(function(conn){
      connection = conn;
      let test = connection.query('select name from records WHERE name=? LIMIT 1',[thename]);
      return test;
  }).then(function(test1){
      console.log("test1"+JSON.stringify(test1)); // result of previous block
      var result = connection.query('select * from users'); // A second query if you want
      connection.end();
 connection = {};
      return result;
  }).catch(function(error){
      if (connection && connection.end) connection.end();
      //logs out the error from the previous block (if there is any issue add a second catch behind this one)
      console.log(error);
  });
1