Comment créer un code javascript non bloquant?

Comment puis-je créer un appel de fonction Javascript simple et non bloqué? Par exemple:

//begin the program console.log('begin'); nonBlockingIncrement(10000000); console.log('do more stuff'); //define the slow function; this would normally be a server call function nonBlockingIncrement(n){ var i=0; while(i<n){ i++; } console.log('0 incremented to '+i); } 

les sorties

 "beginPage" "0 incremented to 10000000" "do more stuff" 

Comment puis-je former cette boucle simple pour exécuter de manière asynchrone et produire les résultats via une fonction de rappel? L'idée est de ne pas bloquer "faire plus de choses":

 "beginPage" "do more stuff" "0 incremented to 10000000" 

J'ai essayé de suivre les didacticiels sur les rappels et les continuations, mais ils semblent tous s'appuyer sur des bibliothèques ou des fonctions externes. Aucun d'entre eux ne répond à la question dans le vide: comment écrire un code Javascript pour être non bloquant?


J'ai cherché très fort cette réponse avant de demander; Ne supposez pas que je n'ai pas regardé. Tout ce que j'ai trouvé est Node.js spécifique ( [1] , [2] , [3] , [4] , [5] ) ou autrement spécifique à d'autres fonctions ou bibliothèques ( [6] , [7] , [8] , [9] , [10] , [11] ), notamment JQuery et setTimeout() . Aidez-moi à écrire un code non bloquant à l'aide de Javascript , et non des outils écrits par Javascript , tels que JQuery et Node. Veuillez relire la question avant de la marquer en double.

SetTimeout avec rappels est le chemin à parcourir. Bien entendu, comprendre que vos champs de fonctions ne sont pas identiques à ceux de C # ou d'un autre environnement multi-thread.

Javascript n'attend pas le rappel de votre fonction pour finir.

Si tu le dis:

 function doThisThing(theseArgs) { setTimeout(function (theseArgs) { doThatOtherThing(theseArgs); }, 1000); alert('hello world'); } 

Votre alerte disparaîtra avant que la fonction que vous avez passée ne le fasse.

La différence étant que cette alerte a bloqué le fil, mais votre rappel n'a pas été fait.

Pour rendre votre boucle non bloquante, vous devez la diviser en sections et permettre à la boucle de traitement des événements JS de consommer des événements d'utilisateurs avant de passer à la section suivante.

La façon la plus simple d'y parvenir est de faire un certain travail, puis d'utiliser setTimeout(..., 0) pour mettre en file d'attente le prochain morceau de travail. De manière cruciale, cette mise en file d'attente permet à la boucle de l'événement JS de traiter les événements qui ont été mis en file d'attente entre-temps avant de passer au prochain travail:

 function yieldingLoop(count, chunksize, callback, finished) { var i = 0; (function chunk() { var end = Math.min(i + chunksize, count); for ( ; i < end; ++i) { callback.call(null, i); } if (i < count) { setTimeout(chunk, 0); } else { finished.call(null); } })(); } 

Avec l'utilisation:

 yieldingLoop(1000000, 1000, function(i) { // use i here }, function() { // loop done here }); 

Voir http://jsfiddle.net/alnitak/x3bwjjo6/ pour une démonstration où la fonction callback définit simplement une variable pour le nombre d'itérations actuel, et une boucle setTimeout séparée permet de rechercher la valeur actuelle de cette variable et met à jour la page avec sa valeur .