Cet exemple est JavaScript, car c'est là que j'utilise les rappels surtout. Je veux comprendre comment ils travaillent à un niveau bas.
Dans l'exemple ci-dessous, je m'attendrais à ce que tout se produise dans l'ordre et "rappel" pour se produire après "étape 3" et avant "Étape 4." Cela a du sens pour moi, car tout est fait pour un seul fil d'exécution. Il n'y a pas de tromperie. La seule chose qui est en quelque sorte spéciale, c'est que vous avez passé une fonction à une autre fonction. P> Comment créeriez-vous Je suppose que si DOSOMODRON code> asynchrone pour que "Étape 4" peut être exécuté avant ou parallèlement, "Étape 3"? P>
DOSMATHIAT code> était appelé d'une manière asynchrone, il faudrait être sur un fil différent, non? Et si oui, quand il finit puis appelle
myCallback code>, est-ce que le rappel se produit sur le deuxième fil ou sur le thread principal? Strong> Si cela se produit sur le fil principal, pourquoi ça se passe Le deuxième thread a même besoin d'un pointeur sur la fonction de rappel? Comment fonctionne l'appel inter-thread? P> P>
4 Réponses :
Vous auriez besoin de plusieurs threads d'exécution pour faire cela, ce que je ne crois pas que vous puissiez faire en JavaScript (bien que corrige-moi si je me trompe). Toutefois, si vous écrivez un programme C / C ++, regardez le package Pthreads (ou libdispatch sur Mac OS X 10.6). P>
Edit: une recherche Google de "threads javascript" présente des résultats potentiellement intéressants. P>
Utilisation de rappels comme vous êtes (nom de déclaration de fonction ou nom de variable d'expression de fonction comme argument à une autre fonction), ils sont synchrones em>. Pour les rendre asynchrones, vous pouvez les envelopper dans un Settimeout code>. P>
webworkers Mister, le modèle de programmation JavaScript dans le navigateur est purement unique. Vous pouvez faire votre appel un peu asynchrone en utilisant fenêtre.settimeout : Cela place efficacement l'appel Une conséquence malheureuse de ce DOSMATHIQUE (MYCALLBACK) CODE> sur la file d'attente de la minuterie, et après 0 ou plusieurs millisecondes ELAPSE, il sera éventuellement invoqué. Cependant, comme avec tous les appels asynchrones en JavaScript, vous devez renoncer au contexte d'exécution avant que les rappels asynchrones puissent être invoqués; c'est-à-dire que la file d'attente de la minuterie ne sera pas traitée (et donc
dosomething (myCallback) code> ne sera pas invoquée) jusqu'à ce que votre
principal () code> Fonction fonction, en supposant que la fin de la fonction Votre JavaScript. p>
Settimeout code> -A-Based est que
DOSMATHIAT (MYCALLBACK) code> n'est pas invoqué en parallèle à côté de
console.log ("étape 4") code>. D'autre part, considérez xmlhttprequest.send ; Après avoir effectué cet appel, le reste de votre JS peut continuer à exécuter pendant que le navigateur émet la requête HTTP. Votre script a besoin de finir d'exécuter avant le ONREADYSTATECHANGE Handler peut exécuter, Mais la plupart des travaux de connexion HTTP peuvent se produire en parallèle pendant que JS exécute. p> p>
Dans le cas code> code>, je suppose que cela se produit sur un autre fil. Quand c'est fait et que le OnreadyStatechange Code> Handler s'exécute, quel fil fait cela se passe-t-il?
Cela se produit sur le fil JavaScript principal. Mise en œuvre, cela peut être n'importe quel fil, mais conceptuellement JavaScript (et le DOM, pour cette affaire) s'exécute dans un seul fil.
Je suppose que la partie déroutante est que cela s'appelle un "rappel". Cela, pour moi, dit "Voici une fonction, appelez ceci lorsque vous avez terminé de faire votre chose. Je vais faire ma propre chose." Lorsque vraiment, le navigateur termine l'appel AJAX puis interrompt le fil principal (via quel mécanisme ??) et le fil principal lui-même appelle la fonction qu'elle enregistrait comme rappel. Ai-je raison?
Conceptuellement, il n'y a pas d'interruption. Pendant un instant, prétendez que le monde n'a pas de concurrence au tout - vous demandez au navigateur de faire un appel AJAX ou de réagir aux clics de souris, mais il ne peut rien faire avant la fin de votre JS. Ce n'est qu'après ce point que le navigateur peut décider de vous informer que le serveur a répondu à votre appel AJAX ou que l'utilisateur a cliqué sur la page; L'interprète JS commence une fois de plus et exécute votre rappel. (Ce n'est pas trop éloigné - le navigateur ne peut pas traiter les événements cliquez, etc. pendant que votre JS fonctionne.)
hmmm .. quelque chose ne va pas mal (j'ai fait v Little JavaScript): vous passez myCallback à la fonction DOSMATHIAT () mais vous ne le rappelez pas !? Vous devriez avoir un appel à F () à l'intérieur du dosage () ou transmettez-le à une autre fonction qui le rappellera une fois que votre longue opération est terminée .. Aucun rappel n'est intrinsèquement asynchrone - dans votre cas, vous exécutez tout cela. Sur le même fil (même si l'accès à l'accès à l'accès () est asynchrone auquel cas cela reviendrait immédiatement!) - Donc, il ira toujours Step1, Step2, Step3, Step4. Je crois que vous voulez:
function main() { console.log("step 1"); console.log("step 2"); doSomething(myCallBack); console.log("step 4"); } function doSomething(f) { accessTheDatabase(f); // assuming this is an asynchronous operation and calls the callback f once done } function myCallBack() { console.log("step 3"); }
Tu as raison! Merci pour la prise.
Mon plaisir, marquez-le comme la réponse si c'est :)
réponse mise à jour pour la 2e partie de votre question - quel filetage il est exécuté
Je suppose que c'est pas i> courir dans un navigateur, non? Parce que dans le navigateur, tout appel AJAX est nécessairement asynchrone ...
@Dean, Tout d'abord, les demandes XHR peuvent être synchrones (selon les paramètres de la demande). Deuxièmement, si vous lisez la question (et regardez son exemple de code), il ne s'agit pas d'Ajax.
@Dean, cela pourrait fonctionner dans un navigateur ou non. Je suis tout à fait intéressé à déterminer si la fonction de rappel est exécutée sur le thread principal ou le deuxième fil qui a été passé le pointeur de la fonction de rappel en tant que paramètre.