web-dev-qa-db-fra.com

Quelle est la différence entre la programmation synchrone et asynchrone (dans node.js)

J'ai lu nodebeginner Et je suis tombé sur les deux morceaux de code suivants.

Le premier:

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

Le deuxième:

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

Je comprends ce qu'ils sont censés faire, ils interrogent la base de données pour récupérer la réponse à la requête. Et puis console.log('Hello world').

Le premier est censé être du code synchrone. Et le second est le code asynchrone.

La différence entre les deux pièces est très vague pour moi. Quelle serait la sortie?

Googler sur la programmation asynchrone ne m'a pas aidé non plus.

179
Azeirah

La différence est que dans le premier exemple , le programme se bloque sur la première ligne. La ligne suivante (console.log) devra attendre.

Dans le deuxième exemple , le console.log sera exécuté Tandis que la requête est en cours de traitement. C'est-à-dire que la requête sera traitée en arrière-plan, pendant que votre programme fait autre chose, et une fois que les données de la requête sont prêtes, vous ferez ce que vous voulez avec.

Donc, en un mot: le premier exemple va bloquer, le second pas.

Le résultat des deux exemples suivants:

// 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");

Serait:

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

Note
Bien que Node soit lui-même à thread unique , certaines tâches peuvent être exécutées en parallèle. Par exemple, les opérations du système de fichiers ont lieu dans un processus différent.

C'est pourquoi Node peut effectuer des opérations asynchrones: un thread effectue des opérations sur le système de fichiers, tandis que le thread principal Node continue à exécuter votre code javascript. Dans un serveur dépendant d'événements, tel que Node, le thread du système de fichiers notifie au thread principal Node de certains événements tels que l'achèvement, l'échec ou la progression, ainsi que des données associées à cet événement (comme le résultat de une requête de base de données ou un message d'erreur) et le thread principal Node décide ce qu'il faut faire de ces données.

Vous pouvez en savoir plus à ce sujet ici: Comment fonctionne le modèle à thread unique non bloquant IO dans Node.js

211
Salvatorelab

La différence entre ces deux approches est la suivante:

Synchrone: Il attend que chaque opération soit terminée, après il exécute uniquement l'opération suivante. Pour votre requête: La commande console.log() ne sera exécutée que le & & sauf si la requête a fini de s'exécuter pour obtenir tous les résultats de Database.

Manière asynchrone: Il n'attend jamais que chaque opération soit terminée, mais exécute toutes les opérations dans le premier GO uniquement. Le résultat de chaque opération sera traité une fois que le résultat sera disponible. Pour votre requête: La commande console.log() sera exécutée peu de temps après la méthode Database.Query(). Pendant que la requête de base de données s'exécute en arrière-plan et charge le résultat une fois les données récupérées.

cas d'utilisation

  1. Si vos opérations ne sont pas très lourdes, telles que l’interrogation de données volumineuses à partir de la base de données, poursuivez avec Synchronous ou autrement Asynchronous.

  2. De manière asynchrone, vous pouvez afficher un indicateur de progression à l’utilisateur alors que vous êtes en arrière-plan, vous pouvez poursuivre vos travaux les plus lourds. C'est un scénario idéal pour les applications à interface graphique.

70
Santosh Panda

Cela deviendrait un peu plus clair si vous ajoutez une ligne aux deux exemples:

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

Le deuxième:

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

Essayez de les exécuter et vous remarquerez que, dans le premier exemple (synchrone), la longueur de resultat sera imprimée AVANT la ligne 'Hello World'. Dans le deuxième exemple (asynchrone), la longueur de resultat sera (le plus probablement) imprimée APRÈS la ligne "Hello World".

En effet, dans le deuxième exemple, le database.query est exécuté de manière asynchrone en arrière-plan et le script continue immédiatement avec le "Hello World". La console.log(result.length) n'est exécutée que lorsque la requête de base de données est terminée.

22
Martijn

Premièrement, je me rends compte que je suis en retard pour répondre à cette question.

Avant de parler de synchrone et d’asynchrone, examinons brièvement le fonctionnement des programmes.

Dans le cas synchrone, chaque instruction se termine avant l'exécution de l'instruction suivante. Dans ce cas, le programme est évalué exactement dans l'ordre des instructions.

Voici comment asynchrone fonctionne en JavaScript. Il existe deux parties dans le moteur JavaScript, une partie traitant du code et des opérations de mise en file d'attente et une autre traitant la file d'attente. Le traitement de la file d'attente s'effectue dans un thread, c'est pourquoi une seule opération à la fois peut avoir lieu.

Lorsqu'une opération asynchrone (telle que la deuxième requête de base de données) est vue, le code est analysé et l'opération est placée dans la file d'attente, mais dans ce cas, un rappel est enregistré pour être exécuté à la fin de l'opération. La file d'attente peut déjà contenir de nombreuses opérations. L'opération au début de la file d'attente est traitée et supprimée de la file d'attente. Une fois que l'opération relative à la requête de base de données est traitée, la demande est envoyée à la base de données. Une fois l'opération terminée, le rappel est exécuté à la fin. A ce stade, le processeur de file d'attente ayant "géré" l'opération passe à l'opération suivante - dans ce cas

    console.log("Hello World"); 

La requête de base de données est toujours en cours de traitement, mais l'opération console.log se trouve en tête de la file d'attente et est traitée. Il s’agit d’une opération synchrone qui s’exécute immédiatement et aboutit immédiatement à la sortie "Hello World". Quelque temps plus tard, l'opération de base de données est terminée, puis le rappel enregistré avec la requête est appelé et traité, en définissant la valeur du résultat de la variable sur des lignes.

Il est possible qu'une opération asynchrone aboutisse à une autre opération asynchrone. Cette seconde opération sera placée dans la file d'attente et sera traitée au début de la file d'attente. L'appel du rappel enregistré avec une opération asynchrone est la façon dont JavaScript exécute le résultat de l'opération à la fin.

Une méthode simple pour savoir quelle opération JavaScript est asynchrone consiste à indiquer si elle nécessite un rappel - le rappel est le code qui sera exécuté à la fin de la première opération. Dans les deux exemples de la question, nous pouvons voir que le second cas a un rappel, il s'agit donc de l'opération asynchrone des deux. Ce n'est pas toujours le cas en raison des différents styles de traitement du résultat d'une opération asynchrone.

Pour en savoir plus, lisez à propos des promesses. Les promesses constituent un autre moyen de gérer le résultat d'une opération asynchrone. La bonne chose à propos des promesses est que le style de codage ressemble plus à du code synchrone.

De nombreuses bibliothèques, telles que node 'fs', fournissent des styles à la fois synchrones et asynchrones pour certaines opérations. Dans les cas où l'opération ne prend pas beaucoup de temps et n'est pas beaucoup utilisée, comme dans le cas de la lecture d'un fichier de configuration, l'opération de style synchrone donnera un code plus facile à lire.

18
Jay

Dans le cas synchrone, la commande console.log n'est pas exécutée tant que la requête SQL n'est pas terminée.

Dans le cas asynchrone, la commande console.log sera exécutée directement. Le résultat de la requête sera ensuite stocké par la fonction "callback" ultérieurement.

5
related

La principale différence réside dans la programmation asynchrone. Sinon, vous n'arrêtez pas l'exécution. Vous pouvez continuer à exécuter un autre code pendant que la "demande" est en cours.

4
thebreiflabb

La fonction rend le second asynchrone.

La première force le programme à attendre que chaque ligne soit terminée avant que la suivante puisse continuer. La seconde permet à chaque ligne de fonctionner ensemble (et indépendamment) à la fois.

Les langages et les frameworks (js, node.js) qui autorisent les accès asynchrones ou simultanés sont parfaits pour les choses qui nécessitent une transmission en temps réel (par exemple, les applications de chat et stock).

2
Anton Chan

Programmation synchrone

Les langages de programmation tels que C, C #, Java sont une programmation de synchronisation. Tout ce que vous écrivez sera exécuté dans l'ordre de votre écriture.

-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 propose une fonctionnalité asynchrone, elle est de nature non bloquante, supposons que dans toute tâche d'E/S prenant du temps (récupération, écriture, lecture), nodejs ne reste pas inactif et attend la fin de la tâche, il ' ll commencera à exécuter les tâches suivantes de la file d’attente et, chaque fois que cette tâche prendrait fin, elle sera notifiée par rappel. Les exemples suivants aideront:

//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();

En bref, la sortie est la suivante:

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 différence est claire là où la synchronisation prendra définitivement plus de 600 (500 + 100 + temps de traitement) msec, async permet de gagner du temps.

0
Neeraj Bansal