114 votes

Comment écrire des fonctions asynchrones pour Node.js

J'ai essayé de faire des recherches sur la façon dont les fonctions asynchrones doivent être écrites. Après avoir parcouru une grande quantité de documentation, je n'ai toujours pas compris.

Comment écrire des fonctions asynchrones pour Node ? Comment mettre en œuvre correctement la gestion des événements d'erreur ?

Une autre façon de poser ma question serait la suivante : Comment dois-je interpréter la fonction suivante ?

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

Aussi, j'ai trouvé cette question sur le SO ("Comment puis-je créer une fonction asynchrone non bloquante dans node.js ?") intéressante. Je n'ai pas l'impression qu'on y ait encore répondu.

14 votes

C'est pour ça que je demande. Je ne vois pas en quoi ces fonctions sont différentes.

0 votes

Je vous recommande de regarder setTimeout y setInterval dans votre navigateur préféré et jouez avec eux également. Vous pouvez aussi utiliser des rappels ajax (ce qui se rapproche probablement le plus de l'expérience des nœuds), ou des écouteurs d'événements pour des choses qui vous sont familières, comme les événements de clic et de chargement. Le modèle asynchrone existe déjà dans le navigateur, et c'est exactement la même chose dans node.

0 votes

@davin - Je suppose que je ne comprends pas bien le modèle asynchrone alors.

85voto

Raynos Points 82706

Vous semblez confondre les entrées/sorties asynchrones avec les fonctions asynchrones. node.js utilise des entrées/sorties asynchrones non bloquantes parce que les entrées/sorties non bloquantes sont meilleures. La meilleure façon de le comprendre est de regarder quelques vidéos de Ryan Dahl.

Comment écrire des fonctions asynchrones pour Node ?

Il suffit d'écrire des fonctions normales, la seule différence étant qu'elles ne sont pas exécutées immédiatement mais transmises en tant que callbacks.

Comment mettre en œuvre correctement la gestion des événements d'erreur

Généralement, les API vous donnent un callback avec un err comme premier argument. Par exemple

database.query('something', function(err, result) {
  if (err) handle(err);
  doSomething(result);
});

C'est un modèle commun.

Un autre modèle commun est on('error') . Par exemple

process.on('uncaughtException', function (err) {
  console.log('Caught exception: ' + err);
});

Editar:

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

La fonction ci-dessus, lorsqu'elle est appelée comme

async_function(42, function(val) {
  console.log(val)
});
console.log(43);

Imprimera 42 à la console de manière asynchrone. En particulier process.nextTick se déclenche une fois que la pile d'appels de l'eventloop actuel est vide. Cette pile d'appels est vide après async_function y console.log(43) ont couru. Nous imprimons donc 43 suivi de 42.

Vous devriez probablement faire quelques lectures sur la boucle d'événement.

0 votes

J'ai vu les vidéos de Dahl, mais je n'ai pas l'air de saisir le sujet, j'en ai peur. :(

1 votes

@Kriem voir réponse mise à jour et lire à propos de la boucle d'événement

1 votes

Merci pour ces informations. Je suis maintenant plus conscient de ce qui me manque en matière de connaissances :) Votre dernier exemple m'a aidé, d'ailleurs.

9voto

user3021198 Points 117

Il ne suffit pas de passer par des callbacks. Vous devez utiliser settimer par exemple, pour rendre la fonction asynchrone.

Exemples : Pas de fonctions asynchrones :

function a() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };
  b();
};

function b() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };    
  c();
};

function c() {
  for(i=0; i<10000000; i++) {
  };
  console.log("async finished!");
};

a();
console.log("This should be good");

Si vous exécutez l'exemple ci-dessus, cela devrait être bon, il faudra attendre que ces fonctions finissent de fonctionner.

Fonctions pseudo multithread (async) :

function a() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };
    b();
  }, 0);
};

function b() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };  
    c();
  }, 0);
};

function c() {
  setTimeout ( function() {
    for(i=0; i<10000000; i++) {
    };
    console.log("async finished!");
  }, 0);
};

a();
console.log("This should be good");

Celui-ci sera vraiment asynchrone. Cela devrait être bon sera écrit avant que l'asynchronisme ne soit terminé.

5voto

Cris-O Points 3334

Tu devrais regarder ça : Node Tuts épisode 19 - Patrons d'itération asynchrones

Il devrait répondre à vos questions.

3voto

ryanwaite28 Points 234

Si vous SAVEZ qu'une fonction renvoie une promesse, je vous suggère d'utiliser les nouvelles fonctionnalités async/await de JavaScript. La syntaxe a l'air synchrone mais fonctionne de manière asynchrone. Lorsque vous ajoutez l'élément async à une fonction, il vous permet de await les promesses dans ce domaine :

async function ace() {
  var r = await new Promise((resolve, reject) => {
    resolve(true)
  });

  console.log(r); // true
}

si une fonction ne renvoie pas une promesse, je recommande de l'envelopper dans une nouvelle promesse que vous définissez, puis de résoudre les données que vous voulez :

function ajax_call(url, method) {
  return new Promise((resolve, reject) => {
    fetch(url, { method })
    .then(resp => resp.json())
    .then(json => { resolve(json); })
  });
}

async function your_function() {
  var json = await ajax_call('www.api-example.com/some_data', 'GET');
  console.log(json); // { status: 200, data: ... }
}

En résumé : exploitez le pouvoir des promesses.

2voto

Pradeep Points 13

Essayez ceci, cela fonctionne à la fois pour le nœud et le navigateur.

isNode = (typeof exports !== 'undefined') &&
(typeof module !== 'undefined') &&
(typeof module.exports !== 'undefined') &&
(typeof navigator === 'undefined' || typeof navigator.appName === 'undefined') ? true : false,
asyncIt = (isNode ? function (func) {
  process.nextTick(function () {
    func();
  });
} : function (func) {
  setTimeout(func, 5);
});

18 votes

4 votes négatifs et pas un seul commentaire constructif :\N

6 votes

@Omer Telle est la vie sur SO.

6 votes

@NorbertoBezi Peut-être que le code est explicite pour vous, mais pas pour celui qui a posté la réponse. C'est pourquoi c'est toujours une bonne pratique d'expliquer lors d'un downvoting.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X