2013-05-02 25 views
143

Sto leggendo nodebeginner E ho trovato i seguenti due pezzi di codice.Qual è la differenza tra la programmazione sincrona e asincrona (in node.js)

Il primo:

var result = database.query("SELECT * FROM hugetable"); 
    console.log("Hello World"); 

Il secondo:

database.query("SELECT * FROM hugetable", function(rows) { 
     var result = rows; 
    }); 
    console.log("Hello World"); 

ottengo quello che si suppone di fare, interrogare il database per recuperare la risposta alla query. E poi console.log('Hello world').

Il primo è apparentemente codice sincrono. E il secondo è un codice asincrono.

La differenza tra i due pezzi è molto vaga per me. Quale sarebbe l'output?

Googling su programmazione asincrona non ha aiutato neanche me.

+23

Stange non hai trovato nulla con google, è un argomento piuttosto grande. Nella programmazione sincrona, ciascun passo viene eseguito uno dopo che l'esecuzione precedente è terminata. In modo asincrono, il passaggio 2 verrà eseguito anche se il passaggio 1 non è terminato. La funzione che vedi definita nel tuo secondo esempio è chiamata funzione callBack e verrà eseguita non appena verrà restituito il risultato dal database, che probabilmente avverrà dopo l'esecuzione di console.log. –

+6

@Bartdude C'era molto sulla programmazione asincrona, ma nessuna spiegazione un po 'semplice su cosa sia e cosa significhi nella pratica. – Azeirah

+0

Evitare le funzioni sincrone, anche durante l'inizializzazione e lo spegnimento –

risposta

163

La differenza è che nel primo esempio , il programma verrà bloccato nella prima riga. La riga successiva (console.log) dovrà attendere.

Nell'esempio secondo, il console.log verrà eseguito MENTRE la query è in fase di elaborazione. Cioè, la query verrà elaborata in background, mentre il tuo programma sta facendo altre cose, e una volta che i dati della query saranno pronti, farai quello che vuoi con esso.

Quindi, in poche parole: il primo esempio verrà bloccato, mentre il secondo no.

L'uscita di due seguenti esempi:

// Example 1 - Synchronous (blocks) 
var result = database.query("SELECT * FROM hugetable"); 
console.log("Query finished"); 
console.log("Next line"); 


// Example 2 - Asynchronous (doesn't block) 
database.query("SELECT * FROM hugetable", function(result) { 
    console.log("Query finished"); 
}); 
console.log("Next line"); 

sarebbe:

  1. Query finished
    Next line
  2. Next line
    Query finished

Note
Mentre nodo stesso è thread singolo, ci sono alcuni compito che può funzionare in parallelo. Ad esempio, le operazioni del file system si verificano in un processo diverso.

Ecco perché il nodo può eseguire operazioni asincrone: un thread esegue le operazioni del file system, mentre il thread del nodo principale continua a eseguire il codice javascript. In un server basato su eventi come Node, il thread del file system notifica al thread principale del nodo alcuni eventi come il completamento, l'errore o lo stato di avanzamento, insieme ai dati associati a quell'evento (come il risultato di una query del database o un errore messaggio) e il thread principale del nodo decide cosa fare con tali dati.

Potete leggere di più su questo qui: How the single threaded non blocking IO model works in Node.js

+9

Fondamentalmente, quando eseguo il primo pezzo di codice, farà qualcosa di simile a questo: 'richiesta di query .; 5 secondi più tardi quando la richiesta è terminata; console.log'; quando il secondo viene eseguito: 'richiesta di query; console.log; lavoro sulla query'; – Azeirah

+1

sì, è tutto. – TheBronx

+0

@TheBronx Il metodo di query non deve essere scritto in un "modo asincrono" o la query sql viene eseguita su un processo diverso (thread non nodo), ecco perché non blocca il thread del nodo? – JohnGalt

4

La principale differenza è con la programmazione asincrona, non interrompere l'esecuzione in caso contrario. È possibile continuare ad eseguire altro codice mentre viene eseguita la "richiesta".

5

Nel caso sincrono, il comando console.log non viene eseguito finché la query SQL non ha completato l'esecuzione.

Nel caso asincrono, il comando console.log verrà eseguito direttamente. Il risultato della query verrà quindi memorizzato dalla funzione "callback" qualche volta dopo.

+1

Ma in realtà vengono chiamati contemporaneamente? La cosa che mi confonde è, nel codice asincrono, il codice reale che viene eseguito contemporaneamente in parallelo? –

+0

Dipende dal processore (è multi-core?) E dal sistema operativo. Vedi http://en.wikipedia.org/wiki/Multithreading_(software)#Multithreading – related

19

Questo sarebbe diventato un po 'più chiaro se si aggiunge una linea per entrambi gli esempi:

var result = database.query("SELECT * FROM hugetable"); 
console.log(result.length); 
console.log("Hello World"); 

Il secondo:

database.query("SELECT * FROM hugetable", function(rows) { 
    var result = rows; 
    console.log(result.length); 
}); 
console.log("Hello World"); 

provare con questi, e si noterà che il primo (sincrono), il risultato. lunghezza verrà stampato PRIMA della linea "Hello World". Nel secondo esempio (asincrono), la lunghezza risultante sarà (molto probabilmente) stampata DOPO la linea "Hello World".

Questo perché nel secondo esempio, lo database.query viene eseguito in modo asincrono sullo sfondo e lo script continua immediatamente con "Hello World". Il console.log(result.length) viene eseguito solo quando la query del database è stata completata.

+1

dici: il result.length sarà ** (molto probabilmente) ** essere stampato DOPO la linea "Hello World". .... perché sarebbe solo "molto probabile"? Penso che sia sempre stampato dopo l'output di console.log. Grazie per il chiarimento :) – humanityANDpeace

+8

@humanityANDpeace: questo è l'intero punto dell'accesso asincrono: tu non sai_ quando sarà fatto. Forse è un database assurdamente veloce e la query del database ritorna anche prima che Javascript arrivi alla linea "Hello World" ... – Martijn

61

La differenza tra questi due approcci è la seguente:

modo sincrono: Si attende ogni completamento dell'operazione, dopo che solo esegue l'operazione successiva. Per la query: Il comando console.log() non verrà eseguito fino a & a meno che la query non abbia completato l'esecuzione per ottenere tutti i risultati dal database.

modo asincrono: Non è mai attende ogni operazione per completare, piuttosto esegue tutte le operazioni nel primo go unico. Il risultato di ciascuna operazione verrà gestito una volta che il risultato sarà disponibile. Per la vostra richiesta: Il comando console.log() verrà eseguito subito dopo il metodo Database.Query(). Mentre la query Database viene eseguita in background e carica il risultato al termine del recupero dei dati.

I casi d'uso

  1. Se le operazioni non stanno facendo il sollevamento molto pesanti, come l'interrogazione di dati enorme da DB poi andare avanti con il modo sincrono altrimenti modo asincrono.

  2. In modalità asincrona è possibile visualizzare un indicatore di avanzamento per l'utente mentre in background è possibile continuare con i lavori pesanti. Questo è lo scenario ideale per le app GUI.

+2

Significa che db.query (cmd, callback) è in esecuzione contemporaneamente (come nei thread)? Stanno correndo allo stesso tempo? –

+0

Nel suo secondo esempio, c'è qualche possibilità che la query termini così velocemente da richiamare prima il callback, prima di 'console.log'? – Fahmi

2

La funzione rende il secondo asincrono.

Il primo forza il programma ad attendere che ogni riga finisca prima che il successivo possa continuare. Il secondo permette a ciascuna linea di correre insieme (e indipendentemente) contemporaneamente.

Le lingue e i framework (js, node.js) che consentono l'asincrona o la concorrenza sono ottimi per le cose che richiedono una trasmissione in tempo reale (ad esempio chat, applicazioni di magazzino).

16

In primo luogo, mi rendo conto di essere in ritardo nel rispondere a questa domanda.

Prima di discutere sincrono e asincrono, esaminiamo brevemente come vengono eseguiti i programmi.

Nel caso sincrono, ogni istruzione completa prima della successiva istruzione viene eseguita. In questo caso il programma viene valutato esattamente in base alle istruzioni.

Questo è il modo in cui asincrono funziona in JavaScript. Ci sono due parti nel motore JavaScript, una parte che esamina le operazioni di codice e accodamento e un'altra che elabora la coda. L'elaborazione della coda avviene in un thread, ecco perché può accadere una sola operazione alla volta.

Quando viene visualizzata un'operazione asincrona (come la seconda query del database), il codice viene analizzato e l'operazione viene inserita nella coda, ma in questo caso viene registrata una richiamata da eseguire al termine dell'operazione. La coda potrebbe già avere molte operazioni. L'operazione nella parte anteriore della coda viene elaborata e rimossa dalla coda. Una volta che l'operazione per la query del database viene elaborata, la richiesta viene inviata al database e al termine verrà eseguita la richiamata al completamento. A questo punto, il processore coda di aver "gestito" L'operazione si sposta sulla successiva operazione - in questo caso

console.log("Hello World"); 

La query database è ancora in fase di elaborazione, ma l'operazione console.log è nella parte anteriore della coda e viene elaborato. Trattandosi di un'operazione sincrona viene immediatamente eseguita con conseguente risultato nell'output "Hello World". Qualche tempo dopo, l'operazione di database viene completata, solo allora il callback registrato con la query viene richiamato ed elaborato, impostando il valore del risultato della variabile su righe.

È possibile che un'operazione asincrona risulti in un'altra operazione asincrona, questa seconda operazione verrà inserita nella coda e quando verrà visualizzata la parte anteriore della coda verrà elaborata. La chiamata al callback registrato con un'operazione asincrona è il modo in cui JavaScript run time restituisce il risultato dell'operazione quando viene eseguita.

Un semplice metodo per sapere quale operazione JavaScript è asincrona è notare se richiede una richiamata - il callback è il codice che verrà eseguito quando la prima operazione è completa. Nei due esempi nella domanda, possiamo vedere solo il secondo caso ha un callback, quindi è l'operazione asincrona dei due. Non è sempre il caso a causa dei diversi stili di gestione del risultato di un'operazione asincrona.

Per ulteriori informazioni, leggi le promesse. Le promesse sono un altro modo in cui è possibile gestire il risultato di un'operazione asincrona. La cosa bella delle promesse è che lo stile di codifica è più simile al codice sincrono.

Molte librerie come il nodo 'fs', forniscono sia stili sincroni che asincroni per alcune operazioni. Nei casi in cui l'operazione non richiede molto tempo e non viene utilizzata molto - come nel caso della lettura di un file di configurazione - l'operazione in stile sincrono produrrà un codice che è più facile da leggere.

0

Sync Programmazione

Linguaggi di programmazione come C, C#, Java sono la programmazione di sincronizzazione, quindi quello che mai si scrive sarà eseguire in ordine di vostra scrittura.

-GET DATA FROM SQL. 
//Suppose fetching data take 500 msec 

-PERFORM SOME OTHER FUNCTION. 
//Performing some function other will take 100 msec, but execution of other 
//task start only when fetching of sql data done (i.e some other function 
//can execute only after first in process job finishes). 

-TOTAL TIME OF EXECUTION IS ALWAYS GREATER THAN (500 + 100 + processing time) 
msec 

Async

NodeJs esce con funzione asincrono, è non-blocking in natura, si supponga che in tutta l'operazione di I/O che si sta tempo (il recupero, la scrittura, la lettura), nodejs ha vinto' t mantenuto inattivo e attendere il completamento dell'attività, inizierà l'esecuzione delle attività successive nella coda e ogni volta che verrà completata l'attività, verrà notificato tramite callback. Seguendo esempio aiuterà:

//Nodejs uses callback pattern to describe functions. 
//Please read callback pattern to understand this example 

//Suppose following function (I/O involved) took 500 msec 
function timeConsumingFunction(params, callback){ 
    //GET DATA FROM SQL 
    getDataFromSql(params, function(error, results){ 
    if(error){ 
     callback(error); 
    } 
    else{ 
     callback(null, results); 
    } 
    }) 
} 

//Suppose following function is non-blocking and took 100 msec 
function someOtherTask(){ 
    //some other task 
    console.log('Some Task 1'); 
    console.log('Some Task 2'); 
} 

console.log('Execution Start'); 

//Start With this function 
timeConsumingFunction(params, function(error, results){ 
    if(error){ 
     console.log('Error') 
    } 
    else{ 
     console.log('Successfull'); 
    } 
    }) 

//As (suppose) timeConsumingFunction took 500 msec, 
//As NodeJs is non-blocking, rather than remain idle for 500 msec, it will start 
//execute following function immediately 
someOtherTask(); 

In breve, l'uscita è come:

Execution Start 
//Roughly after 105 msec (5 msec it'll take in processing) 
Some Task 1 
Some Task 2 
//Roughly After 510 msec 
Error/Successful //depends on success and failure of DB function execution 

differenza è chiaro dove la sincronizzazione sarà sicuramente prendere più di 600 (500 + 100 + tempo di elaborazione) msec, async risparmia tempo.

Problemi correlati