J'ai un appel Ajax qui doit actuellement être synchrone. Toutefois, alors que cet appel AJAX est exécuté, l'interface du navigateur gèle jusqu'à ce que l'appel renvoie. En cas de délai d'attente, cela peut geler le navigateur pour un période significative . < P> Y a-t-il un moyen d'obtenir le navigateur (n'importe quel navigateur) pour actualiser l'interface utilisateur, mais n'exécuter aucun JavaScript? Idéalement, ce serait une commande comme Si cela serait possible, je pourrais remplacer l'appel Ajax synchrone avec quelque chose comme: p> la raison que je ne peux pas utiliser window.update () code>, qui permettrait à l'interface utilisateur thread thread rafraîchir. P>
SetTimeout code> ou reprendre une fonction dans le rappel, est-ce que le flux d'exécution ne peut pas Soyez interrompu: (Il y a beaucoup trop de variables d'état qui dépendent tous les uns sur les autres, et le flux code> long_function () code> devrait être repris en quelque sorte): p>
4 Réponses :
Prenez le reste de l'appel et mettez-le dans le rappel appelé lorsque le résultat revient. Je doute sérieusement que cela serait complètement impossible pour vous de faire. Toute logique que vous devez placer dans l'appel peut être dupliquée dans le rappel P>
Ajax Ajax Asynchrone Fetch puis Settimeout et faire le travail de traitement en morceaux (déclenchés par le rappel) p>
Vous devez remplacer votre demande synchrone avec une demande asynchrone et utiliser un rappel. Un exemple trop simplifié serait:
obj = do_async_ajax_call(function (data, success) { if (success) { // continue... } }); function do_async_ajax_call(callback) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://mysite.com", true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) callback(xhr.responseXML, true); else if (xhr.readyState == 4) callback(null, false); } xhr.send(); }
Cela serait normalement suffisant, mais je ne peux pas scinder le flux de fonctionnement (comme mis à jour dans la question). J'essaye une autre approche maintenant ...
C'est toujours i> possible de la diviser; Ceci est la transformation CPS (recherchez «Style de passage de continuation»; le paramètre de continuation est votre rappel). Vos variables d'état local sont simplement fermées dans la fonction de rappel. Les boucles deviennent des appels récursifs. Ce n'est pas si difficile ou obscur une fois que vous avez compris.
Je suis d'accord que c'est toujours possible, mais dans ce cas, ce n'était pas la meilleure solution (il y avait trop de variables d'état!) :) À la fin, j'ai utilisé le résultat des rappels précédents (ou un sondage régulier du serveur) pour mettre à jour le client- Côté avec une valeur mise en cache de l'appel synchrone si nécessaire, il n'a donc pas besoin d'appeler Ajax du tout.
JavaScript est un seul thread. Donc, par définition, vous ne pouvez pas mettre à jour l'interface utilisateur pendant que vous êtes dans une boucle de marée. Cependant, à partir de Firefox 3.5, il a ajouté des javascripts multi-threads appelés webriers. Les travailleurs Web ne peuvent pas affecter l'interface utilisateur de la page, mais ils ne bloqueront pas non plus les mises à jour de l'interface utilisateur. Les travailleurs sont également soutenus par Chrome et Safari.
Problème est que même si vous déplacez votre appel AJAX en filetage d'arrière-plan et que vous attendez de l'exécution, les utilisateurs pourront appuyer sur les boutons et modifier des valeurs sur votre UI (et aussi loin que je comprenne, c'est ce que vous essayez de éviter). La seule chose que je peux suggérer d'empêcher que les utilisateurs puissent entraîner des modifications est une fileuse qui bloquera l'intégralité de l'interface utilisateur et ne permettra aucune interaction avec la page jusqu'à ce que l'appel Web renvoie. P>
Je ne me dérange pas si les utilisateurs interagissent avec la page (et l'interaction est la file d'attente); Mais actuellement, lorsqu'un appel AJAX synchrone est exécuté dans Firefox, tout le navigateur gèle. C'est ce que je veux empêcher.
Pourquoi l'appel doit-il être synchrone?
Pouvez-vous publier tout le code d'appel? Cela peut probablement être simplifié et utiliser les fonctions XHR pour prendre en charge ce dont vous avez besoin (à moins que JQuery ne soit une option, alors encore plus propre). Si aucune option n'est ni une option, je vous demande de renommer la fonction à
do_sync_jax_call (); code>