Vor ein paar Tagen habe ich folgende Frage gestellt:
Ich feuere sechs asynchrone jQuery-Ajax-Anforderungen gleichzeitig mit derselben Controller-Aktion ab. Jede Anfrage benötigt 10 Sekunden, um zurückzukehren.
Durch das Debuggen und Protokollieren von Anforderungen an die Aktionsmethode stelle ich fest, dass die Anforderungen serialisiert sind und niemals parallel ausgeführt werden. dh ich sehe eine Zeitleiste in meinen log4net-Protokollen wie folgt:
2010-12-13 13: 25: 06,633 [11164] INFO - Got: 1156 2010-12-13 13: 25: 16,634 [11164] INFO - Rückgabe: 1156 2010-12-13 13: 25: 16,770 [7124] INFO - Got: 1426 2010-12-13 13: 25: 26,772 [7124] INFO - Rückgabe: 1426 2010-12-13 13: 25: 26,925 [11164] INFO - Got: 1912 2010-12-13 13: 25: 36,926 [11164] INFO - Rückgabe: 1912 2010-12-13 13: 25: 37,096 [9812] INFO - Got: 1913 2010-12-13 13: 25: 47,098 [9812] INFO - Rückgabe: 1913 2010-12-13 13: 25: 47,283 [7124] INFO - Got: 2002 2010-12-13 13: 25: 57,285 [7124] INFO - Rückgabe: 2002 2010-12-13 13: 25: 57,424 [11164] INFO - Got: 1308 2010-12-13 13: 26: 07,425 [11164] INFO - Rückgabe: 1308
Wenn ich mir die Netzwerkzeitleiste in FireFox ansehe, sehe ich Folgendes:
Sowohl das obige Protokollbeispiel als auch die Firefox-Netzwerkzeitleiste gelten für denselben Anforderungssatz.
Werden Anforderungen an dieselbe Aktion von derselben Seite serialisiert? Mir ist der serialisierte Zugriff auf das Session
Objekt in derselben Sitzung bekannt, aber es werden keine Sitzungsdaten berührt.
Ich habe den clientseitigen Code auf eine einzelne Anfrage (die am längsten laufende) reduziert, aber dies blockiert den Browser immer noch, dh nur wenn die Ajax-Anfrage abgeschlossen ist, reagiert der Browser auf einen Link-Klick.
Was ich hier (in den Entwicklertools von Chrome) auch beobachte, ist, dass beim Klicken auf einen Link, wenn eine lange laufende Ajax-Anfrage ausgeführt wird, Failed to load resource
sofort ein Fehler gemeldet wird, der darauf hindeutet, dass der Browser den Ajax getötet hat (oder versucht, ihn zu töten und zu warten?) Anfrage:
Es dauert jedoch noch einige Zeit, bis der Browser zur neuen Seite umleitet.
Sind Ajax-Anfragen wirklich asynchron oder ist dies ein Kinderspiel, weil Javascript tatsächlich Single-Threaded ist?
Dauern meine Anfragen einfach zu lange, damit dies funktioniert?
Das Problem tritt auch in Firefox und IE auf.
Ich habe auch das Skript so geändert, dass es $.ajax
direkt und explizit festgelegt wird async: true
.
Ich führe dies unter IIS7.5 aus. Sowohl die Windows 2008R2- als auch die Windows 7-Version machen dasselbe.
Debug- und Release-Builds verhalten sich ebenfalls gleich.
Antworten:
Die Antwort starrte mich ins Gesicht.
Ärgerlicherweise hatte ich diesen Absatz vor ein paar Wochen überflogen, ohne die volle Wirkung der kühnen Sätze wirklich zu berücksichtigen. Ich hatte gelesen, dass einfach "Zugriff auf den Sitzungsstatus serialisiert ist" und nicht "alle Anforderungen, unabhängig davon, ob Sie den Sitzungsstatus berühren oder nicht, serialisiert werden", wenn die Anforderungen aus derselben Sitzung stammen.
Glücklicherweise gibt es in ASP.NET MVC3 eine Problemumgehung und es ist möglich, sitzungslose Controller zu erstellen. Scott Guthrie spricht hier darüber:
Ich habe MVC3 RC2 installiert und das Projekt aktualisiert. Das Dekorieren des betreffenden Controllers mit
[SessionState(SessionStateBehavior.Disabled)]
löst das Problem.Und natürlich habe ich das normalerweise erst vor ein paar Minuten in Stack Overflow gefunden:
quelle
[SessionState(SessionStateBehavior.Disabled)]
möglicherweise eine Sicherheitsverletzung in Ihrer Anwendung auslöst, z. B. den Zugriff auf private Daten bei mehreren gleichzeitigen Anforderungen. Mit dieser Option können Sie nicht feststellen, ob ein Benutzer protokolliert ist oder ob eine Sitzung aktiv ist usw. Wenn Sie Sie müssen auf die Sitzung zugreifen, die Sie verwenden können[SessionState(SessionStateBehavior.ReadOnly)]
, damit Sie weiterhin Zugriff auf Ihre Sitzung haben, obwohl Sie sie nicht bearbeiten können, aber in vielen Fällen dennoch hilfreich sein können.SessionStateBehavior.ReadOnly
. Ich habe das Gefühl, dass ich mir das angeschaut habe und dass es immer noch einen serialisierten Zugriff auf Ihre verursachtSession
. Die App verwendet die Formularauthentifizierung sowie eine Cookie / DB-Suchkombination, um den Zugriff auf diesen Controller zu sperren. Die vom Controller selbst zurückgegebenen Daten sind nicht vertraulich, aber wir haben Maßnahmen ergriffen, um zu verhindern, dass Menschen aus müßiger Neugier herumspielen.Ich habe versucht, dies zu reproduzieren, konnte es aber nicht. Hier ist mein Test:
private static readonly Random _random = new Random(); public ActionResult Ajax() { var startTime = DateTime.Now; Thread.Sleep(_random.Next(5000, 10000)); return Json(new { startTime = startTime.ToString("HH:mm:ss fff"), endTime = DateTime.Now.ToString("HH:mm:ss fff") }, JsonRequestBehavior.AllowGet); }
Und der Anruf:
<script type="text/javascript" src="/scripts/jquery-1.4.1.js"></script> <script type="text/javascript"> $(function () { for (var i = 0; i < 6; i++) { $.getJSON('/home/ajax', function (result) { $('#result').append($('<div/>').html( result.startTime + ' | ' + result.endTime )); }); } }); </script> <div id="result"></div>
Und die Ergebnisse:
13:37:00 603 | 13:37:05 969 13:37:00 603 | 13:37:06 640 13:37:00 571 | 13:37:07 591 13:37:00 603 | 13:37:08 730 13:37:00 603 | 13:37:10 025 13:37:00 603 | 13:37:10 166
Und die FireBug-Konsole:
Wie Sie sehen, wird die AJAX-Aktion parallel ausgeführt.
AKTUALISIEREN:
Es scheint, dass in meinen ersten Tests die Anforderungen tatsächlich in FireFox 3.6.12 und Chrome 8.0.552.215 in die Warteschlange gestellt werden, wenn sie verwendet werden$.getJSON()
. Es funktioniert gut in IE8. Meine Tests wurden mit einem ASP.NET MVC 2-Projekt, VS2010, Cassini-Webserver, Windows 7 x64-Bit durchgeführt.Nun , wenn ich ersetzen$.getJSON()
mit$.get()
ihm gut unter allen Browsern funktioniert. Das lässt mich glauben, dass es etwas gibt,$.getJSON()
das dazu führen kann, dass die Anforderungen in die Warteschlange gestellt werden. Vielleicht könnte jemand, der mit den Interna des jQuery-Frameworks besser vertraut ist, mehr Licht in diese Angelegenheit bringen.UPDATE 2:
Versuchen Sie die Einstellung
cache: false
:$.ajax({ url: '/home/ajax', cache: false, success: function (result) { $('#result').append($('<div/>').html( result.startTime + ' | ' + result.endTime )); } });
quelle
$.getJSON()
durch zu ersetzen$.get()
? Ich habe das mit Cassini getestet. Ich habe IIS nicht installiert und kann es nicht überprüfen.$.getJSON()
und bin direkt zu gegangen$.ajax()
und die Ergebnisse sind die gleichen.$.getJSON()
durch$.get()
einen Unterschied? Für mich macht es einen Unterschied. Bei Verwendung$.getJSON
scheinen die Anforderungen in der Warteschlange zu stehen.