Qual è la differenza tra programmazione sincrona e asincrona (in node.js)

Ho letto nodebeginner e ho trovato i seguenti due pezzi di codice.

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 dovrebbero fare, interrogano 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 mi ha aiutato neanche.

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

Nel secondo esempio , console.log verrà eseguito mentre la query viene elaborata. 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 si bloccherà, mentre il secondo no.

L’output dei seguenti due 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

Nota
Mentre il nodo stesso è a thread singolo , esistono alcune attività che possono essere eseguite in parallelo. Ad esempio, le operazioni del file system si verificano in un processo diverso.

Ecco perché il nodo può fare operazioni asincrone: un thread sta facendo operazioni sul 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.

Puoi leggere ulteriori informazioni al riguardo qui: Come funziona il modello IO non bloccante a thread singolo in Node.js

La differenza tra questi due approcci è la seguente:

Modo sincrono: aspetta che ogni operazione venga completata, dopodiché esegue solo l’operazione successiva. Per la tua query: il comando console.log() non verrà eseguito fino a quando la query non avrà completato l’esecuzione per ottenere tutti i risultati dal database.

Modo asincrono: non attende mai il completamento di ogni operazione, ma esegue tutte le operazioni solo nel primo GO. Il risultato di ciascuna operazione verrà gestito una volta che il risultato sarà disponibile. Per la tua query: 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.

Casi d’uso

  1. Se le tue operazioni non stanno facendo grossi sforzi come interrogare enormi dati dal DB, vai avanti con il modo sincrono in modo asincrono.

  2. In modo asincrono è ansible mostrare un indicatore di progresso all’utente mentre in background è ansible continuare con i lavori pesanti. Questo è lo scenario ideale per le app GUI.

Ciò diventerebbe un po ‘più chiaro se si aggiunge una linea ad 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"); 

Prova a eseguirli e noterai che il primo (sincrono) esempio, 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, database.query viene eseguito in modo asincrono sullo sfondo e lo script continua immediatamente con “Hello World”. Il file console.log(result.length) viene eseguito solo quando la query del database è stata completata.

Per prima cosa, mi rendo conto di essere in ritardo nel rispondere a questa domanda.

Prima di discutere sincroni e asincroni, esaminiamo brevemente come funzionano i programmi.

Nel caso sincrono , ogni istruzione viene completata prima dell’esecuzione della prossima istruzione. In questo caso il programma viene valutato esattamente in base alle istruzioni.

Questo è il modo in cui funziona asincrono 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 di coda che ha “gestito” l’operazione si sposta sull’operazione successiva, in questo caso

  console.log("Hello World"); 

La query del database è ancora in fase di elaborazione, ma l’operazione console.log è in testa alla coda e viene elaborata. 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.

È ansible 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 saperne di più, leggi le promesse. Le promesse sono un altro modo in cui è ansible 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.

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.

La differenza principale è con la programmazione asincrona, altrimenti non si arresta l’esecuzione. È ansible continuare ad eseguire altro codice mentre viene eseguita la “richiesta”.

La funzione rende il secondo asincrono.

Il primo forza il programma ad aspettare che ogni linea finisca, prima che il prossimo 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 azionarie).

Programmazione di sincronizzazione

I linguaggi di programmazione come C, C #, Java sono la programmazione di sincronizzazione, ciò che mai scriverai sarà eseguito in ordine di 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 (ie 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 presenta una funzione asincrona, è di natura non bloccante, supponiamo in qualsiasi attività I / O che richiede tempo (recupero, scrittura, lettura), nodejs non verrà tenuto inattivo e aspetterà che l’attività sia finita, esso ‘ Inizierò ad eseguire le prossime attività in coda, e ogni volta che il tempo di completare l’attività verrà notificato tramite callback. L’esempio seguente 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’output è 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 

La differenza è evidente dove la sincronizzazione impiegherà sicuramente più di 600 (500 + 100 + tempi di elaborazione) msec, async consente di risparmiare tempo.