comment créer une fonction asynchrone non-bloquante dans le noeud.js?

comment créer une fonction asynchrone non-bloquante? Ci-dessous est ce que j'essaie d'atteindre, mais mon programme bloque toujours...

var sys = require("sys");

function doSomething() {
  sys.puts("why does this block?");
  while(true);
}

setTimeout(doSomething,0);
setTimeout(doSomething,0);
setTimeout(doSomething,0);

sys.puts("main");
22
demandé sur Richard 2010-05-21 01:31:03

9 réponses

Cross-posté de Reddit .


le but des fonctions asynchrones en JavaScript est un peu différent de ce que vous recherchez.

rappelez-vous que JavaScript est mono - threadé-il ne peut faire qu'une chose à la fois. Voici un code de blocage traditionnel:

sys.puts("Before");
sleep(10);
sys.puts("After");

dans une application web du monde réel, le sleep() pourrait être plutôt une longue appel de base de données, Demande de réseau (comme l'attente de données à partir du navigateur web de l'Utilisateur), outil d'aide, ou l'accès au fichier.

si vous avez utilisé le blocage des appels comme ci-dessus, le noeud.js server ne pourrait rien faire d'autre (comme commencer à gérer d'autres requêtes web) en attendant.

PHP et beaucoup d'autres environnements de programmation web gèrent cela en créant des threads totalement séparés pour chaque requête. Nœud.js utilise des fonctions de rappel. Vous pouvez écrire le même code comme ceci, à la place:

sys.puts("Before");
setTimeout(function(){
    sys.puts("After");
}, 10000);

ici, vous créez une fonction et la passez à setTimeout() . Son code n'est pas encore lancé, mais quand il le sera, il aura accès à toutes les variables (scope) où il a été créé. setTimeout() obtient une référence à la fonction et planifie un événement à déclencher sur la boucle d'événement après l'expiration du délai.

la boucle d'événement est essentiellement un noeud.la liste des tâches du programme js (ils sont commun - toutes les applications GUI tournant sur votre ordinateur utilisent probablement des boucles d'événements!).

après l'appel à setTimeout() , la fonction courante continue d'exécuter. Il retourne éventuellement, et la fonction qui l'a appelé retourne, et ainsi de suite, jusqu'à ce que le programme revienne dans la boucle d'événement. La boucle d'événement regarde pour voir si quelque chose s'est passé (par exemple une requête entrante) pendant que votre code était en cours d'exécution, et appelle la fonction appropriée dans votre code. Si non, il attend jusqu'à ce que quelque chose fait arriver (comme le délai expirant).

code Asynchrone n'est pas laissez votre code faire beaucoup de choses en même temps, il ne éliminer le blocage lorsqu'un code dépend de quelque chose d'extérieur à continuer.

il est rare que vous ayez besoin de faire du travail de blocage à l'intérieur de votre noeud.programme js. Si vous le faites, vous devriez séparer ce travail en un processus séparé (qui peut-être même un autre Nœud.js program), ou écrire A C / C++ addon qui est libre d'utiliser des threads.

33
répondu s4y 2011-08-01 19:30:13

vous ne pouvez faire L'IO asynchrone que dans le noeud.js en utilisant des fonctions IO asynchrones fournies par le noeud.js runtime ou node.extensions js écrites en C++. Votre propre code Javascript est toujours synchrone dans le noeud.js. Le code asynchrone non-IO est rarement nécessaire, et le noeud.js créateurs ont décidé de l'éviter à tout.

il y a des façons obscures d'exécuter Javascript de façon asynchrone dans node.js, mentionné par d'autres commentateurs, mais le nœud.js n'est pas conçu pour ce type de travail. Utiliser Erlang si vous avez besoin de ce type de concurrence, noeud.js est seulement au sujet de paralell IO, et pour les calculs parallèles il est tout aussi mauvais que Python ou PHP.

14
répondu nponeccop 2011-07-18 19:53:08

Vous devez exécuter votre fonction de blocage dans un processus séparé.

ce module peut aider: http://github.com/cramforce/node-worker

10
répondu Felix Geisendörfer 2010-05-20 23:08:06

si vous ne voulez pas utiliser L'API / node-worker de WebWorker, qui est encore très alpha, il suffit de créer un programme node supplémentaire et de communiquer via TCP ou HTTP.

cela vous permet d'envoyer votre travail sous forme D'appels HTTP ou de données TCP brutes et d'attendre de façon asynchrone la réponse HTTP / TCP entrante.

Note cependant, ceci n'est approprié que si votre tâche est facilement sérialisable.

4
répondu b_erb 2010-05-21 10:49:58

setTimeout ne créera pas de nouveau thread, donc le navigateur sera toujours suspendu à la boucle infinie.

vous devez repenser la structure de votre programme.

3
répondu kennytm 2010-05-20 21:36:20

Vous pouvez le faire sans l'aide d'un processus enfant à l'aide de nextTick()

j'étais en train de lire cette explication l'autre jour à propos de nextTick... C'est une grande lecture IMO

---edit: le lien est mort. Trouvé un nouveau droit sur StackOverflow

comprendre le nœud.js file d'attente d'événements et de processus.nextTick

3
répondu ControlAltDel 2018-04-20 15:59:16

si je comprends ce que vous cherchez, vous avez deux fonctions (les deux prennent un argument callback):

process.nextTick : cette fonction peut être empilée, ce qui signifie que si elle est appelée récursivement, elle bouclera un énorme ( process.maxTickDepth ) nombre de fois par Tic de la boucle d'événement.

ou

setImmediate : cette fonction est beaucoup plus proche du réglage d'un délai 0 (mais se produit avant).

Dans la plupart des cas, vous je préfère setImmediate.

2
répondu Sheraff 2014-05-28 17:23:36

je suppose que vous expérimentez avec Nodejs aussi je suppose que vous n'écrivez aucun module npm lui-même et l'exportation de votre fonction en tant que fonction asynchrone, dans la pratique, vous ne rencontrerez pas un tel cas, si vous voulez faire des opérations de blocage dans les fonctions ou dans les callbacks qui sont exécutés dans un environnement de thread simple, essayer d'utiliser des modules de noeud appropriés comme fs pour la lecture de fichiers, la demande de requête réseau et le module async qui donne divers types de opérations asynchrones, rappelez-vous aussi que vous essayez d'exécuter le code de consommation cpu asynchrone c'est une mauvaise idée, parce que 2HZ peut exécuter un million de lignes de code en un peu moins de microsecondes

le but principal de nodejs est de résoudre le problème que vous avez posé dans la question qui est traitée par le libuv sous-jacent pour gérer les événements asynchrones, j'apprécie la réponse d'utiliser le temps d'arrêt défini, mais vous ne savez pas combien de temps à attendre ou à l'aide de l'opérateur de noeud est très bien, mais vous finirez par écrire beaucoup de code de Plaque de chaudière, donc simplement rechercher le module npm qui satisferait votre besoin.

0
répondu murali krish 2017-04-23 11:50:56

Cette ligne:

while(true);

n'est pas "bloquer", c'est juste occupé, pour toujours.

-6
répondu Matt Ranney 2010-05-20 23:14:19