2015-09-29 14 views
6

Sto lavorando alla creazione di un sistema di registrazione utente per un sito Web su cui sto lavorando ma sto riscontrando alcuni problemi.Node.js Domande sincrone con MySQL

sto cercando di stare lontano da dover callback nido, perché diventa un po 'disordinato, Quello che ho bisogno di aiuto con sta trovando se c'è un modo per creare query sincrone con il nodo-mysql

Ecco quello che ho sto cercando di ottenere.

connection.query("select 1 as email from users where email = " + connection.escape(email), function(err, rows, fields) { 
    if(err) { 
     var error = { 
      error_message: err.code, 
      error_number: err.errno 
     }; 

     return res.send(error); 
    } 

    if(rows.length > 0) { 
     var error = { 
      message: 'Email Address is Taken', 
      code: 2 
     }; 
     return res.send(error); 
    } 
}); 

connection.query("insert into users (email, password) values ("+connection.escape(email)+", "+connection.escape(hash)+")", function(err, rows, fields) { 
      if(err) { 
       var error = { 
        error_message: err.code, 
        error_number: err.errno 
       }; 

       return res.send(error); 
      } 
     }); 

Il mio obiettivo è quello di avere la prima esecuzione di query e se che restituisce una riga quindi di non eseguire la seconda query, ma se la prima query restituisce 0 righe poi continuare ed eseguire la seconda query.

So che posso annidare la seconda query all'interno della prima query e inserirla in un altro ma è quello che non voglio fare perché mentre ho queste due query ho anche bisogno di usare bcrypt per crittografare la password che dovrebbe essere annidata pure.

C'è un modo per scriverlo in modo che non sia necessario nidificare le due query o nidificarle diventeranno la mia unica opzione?

+0

Devi nido loro. –

+0

Non è necessario utilizzare il raggruppamento. È possibile utilizzare la cascata asincrona e passare una variabile vero/falso tra i passaggi. Se non puoi voler eseguire la seconda query, passa semplicemente false dal primo. – CargoMeister

+4

Se hai intenzione di sviluppare in node.js, dovrai imparare come scrivere un buon codice asincrono dato che questo è un elemento architettonico principale di node.js e se stai costruendo un server, devi usare le operazioni asincrone per mantenere alcun senso di reattività e scalabilità del server. Potrebbe anche iniziare ora. Suggerirei di imparare come usare le promesse in modo da poter concatenare operazioni sequenziali piuttosto che nidificare e rende più semplice gestire gli errori a tonnellate. – jfriend00

risposta

9

Come detto in precedenza da jfriend00, se hai intenzione di sviluppare in node.js, DEVI diventare comodo con la scrittura del codice asincrono.

"promesse incatenato" è probabilmente la soluzione migliore:

APPENDICE:

Questo tutorial illustra promessa concatenamento con node.js Query SQL. Si discute anche come è possibile utilizzare Q e/o Step per semplificare il codice:

+0

Grazie per gli esempi. Quindi, per quello che sto cercando di fare se dovessi usare le promesse, come potrei fare in modo che io non debba annidare le query? Da quest'ultimo esempio ho iniziato a implementare promesse nel mio codice e questo è quello che ho finora 'Q.ninvoke (db," ​​query ", 'SELECT 1 come email_exists Dagli utenti WHERE email =' + db.escape (email)) .poi (function() {righe se (righe [0] .length> 0) { errore = { error_message: 'Indirizzo e-mail è preso', error_code: 8 }; res.end (errore } }) ma non ho ancora bisogno di nidificare la seconda query nell'istruzione else che è in poi –

+0

Oppure posso avere la seconda query in un altro .then (function() {}); dopo il primo? –

10

Si potrebbe semplicemente utilizzare un modulo per il nodo che forniscono funzioni sincrone. Qui troverai un modulo che fornisce funzioni sync/async per gestire mysql.

https://github.com/Will-I4M/node-mysql-libmysqlclient

Ecco come si potrebbe usare per eseguire una query sincrona:

var config = require("./config.json") ; 
var mysql = require('mysql-libmysqlclient') ; 
var client = mysql.createConnectionSync(config.host, config.user, config.password, config.database) ; 

var query = "SELECT * FROM Users ;" ; 
var handle = client.querySync(query) ; 
var results = handle.fetchAllSync() ; 

console.log(JSON.stringify(results)) ; 
+0

Grazie per questo! In realtà avevo bisogno di una lib sincrona per incatenarli in un gruppo di riduttori. –

+0

questa dovrebbe essere la risposta accettata –

+0

Come nota a margine, un riduttore non è un vero riduttore (perde tra l'altro la sua capacità di essere testato facilmente) se non è una funzione pura che restituisce un valore costantemente basato sui suoi argomenti. Nessun effetto collaterale, non ottenere dati separatamente da una fonte esterna. –

1

Per la maggior parte del codice cose che ho in node.js, mi piace codice asincrono. Tuttavia, capisco perfettamente che il codice asincrono è estremamente e pericolosamente incompatibile con la necessità di scrivere e mantenere la logica aziendale. Ho usato una varietà di metodi alternativi. I moduli per rendere le cose sincrone ti lasciano ancora problemi di scoping dei dati che complicano le cose. Le promesse hanno funzionato meglio per me. Usando questo approccio, mi sono trovato praticamente a scrivere un interprete per una nuova lingua su JavaScript. Potrei sembrare assurdo ma il metodo più pratico e sicuro per me è stato l'utilizzo del modulo shelljs e del client shell mysql.Non si tratta di prestazioni di esecuzione eccezionali, ma offre prestazioni di sviluppo decisamente migliori e mantiene la logica di business chiara e ordinata, così come fondamentale per la logica di business. Ecco uno snippet di codice per dare un esempio di ciò che ho creato:

var shell = require ('shelljs');

module.exports = { utente: '', password '',

runSql:function(sql) { 
      var command = "echo '" + sql.replace(/'/g,"'\\''") + "' | mysql -u" + this.user.replace(/'/g,"'\\''") + " -p'" + this.password.replace(/'/g,"'\\''") + "'"; 
      var raw = shell.exec(command, {silent:true}).stdout; 
      //console.log('BASH -> MySQL YIELD: "' + raw + '"'); 
      if(raw.substr(0,5) === 'ERROR') { 
        console.log('ERROR Resulting from: ' + sql + '\n' + raw); 
        return []; 
      } 
      var rows = raw.split('\n'); 
      var names = []; 
      for(var r = 0; r < rows.length; r += 1) { 
        columns = rows[r].split('\t'); 

        // Capture column names 
        if(r === 0) { 
          names = columns; 
          continue; 
        } 

        // Reformat row into named valued 
        var fields = {}; 
        for(var c = 0; c < columns.length; c += 1) { 
          fields[names[c]] = columns[c]; 
        } 
        rows[r] = fields; 
      }; 

      // Eliminate extraneous first and last rows 
      rows.splice(0,1); 
      rows.splice(rows.length-1,1); 

      return rows; 
    }, 
+0

Successivamente, ho aggiunto qualcosa per verificare se si è verificato un errore e ho segnalato che ... E ho scritto un altro metodo che utilizza questo metodo per ottenere informazioni sulla progettazione della tabella, tramite il comando "Descrivi tablename" di MySQL. Funziona alla grande. Dopo tanto dolore cercando approcci tecnicamente più appropriati sostenuti da persone che non capiscono il bisogno, posso vivere con me stesso facendo così. alla fine, qualcuno deve scrivere un modulo MySQL che offra sia metodi sincroni che asincroni. Personalmente, vorrei davvero che JavaScript avesse una dichiarazione "fai insieme {..}" e "fai in ordine {..}". – user1018645