[JS] Variabele buiten scope van AJAX request*

Pagina: 1
Acties:

  • .Alex
  • Registratie: Augustus 2005
  • Laatst online: 01-08-2022
Hallo allemaal,

Stel, ik heb de volgende functie:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function functie(var1, var2)
{
    var oXmlHttp = createXMLHttp();
    oXmlHttp.open("get", "xmlbestand.php?var1="+var1+"&var2="+var2, true);
    oXmlHttp.onreadystatechange = function()
    {
        if(oXmlHttp.readyState==4)
        {
            if(oXmlHttp.status==200)
            {
                var response = oXmlHttp.responseXML.documentElement;
                xml_iets=response.getElementsByTagName('iets')[0].firstChild.data;
        
                // hoe nu de variabele xml_iets returnen?

            }
        }
    };
    oXmlHttp.send(null);

}

var bla = functie('iets1', 'iets2');


Ik krijg het dus niet voor elkaar om de variabele bla de waarde van xml_iets te geven omdat er een functie in een functie zit waarschijnlijk. Het is lastig hier een oplossing voor te google'en en ik kom er dus maar niet uit. Kunnen jullie me een stap op weg helpen?

  • user109731
  • Registratie: Maart 2004
  • Niet online
Het is niet echt een functie in een functie, wat jouw code nu doet is ongeveer dit:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function functie(var1, var2)
{
    var oXmlHttp = createXMLHttp();
    oXmlHttp.open("get", "xmlbestand.php?var1="+var1+"&var2="+var2, true);
    oXmlHttp.onreadystatechange = onReceived;
    oXmlHttp.send(null);
}
function onReceived()
{
    if(oXmlHttp.readyState==4)
    {
        // etc.
    }
}
var bla = functie('iets1', 'iets2');

In onReceived zit je dus in een hele andere scope, buiten functie(). Meestal word op de plek waar xml_iets binnenkomt de data verwerkt... Asynchroon, vandaar de eerste A in AJAX: Asynchronous JavaScript and XML :)

Voor wat jij wil kun je synchrone requests gebruiken (de derde parameter aan open() is dan false). Zoiets:
JavaScript:
1
2
3
xmlHttp.open("GET", url, false);                             
xmlHttp.send(null);
return xmlHttp.responseText; 

[ Voor 7% gewijzigd door user109731 op 26-06-2007 23:34 . Reden: Iets verduidelijkt nav Erkens' post ]


  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

JanDM schreef op dinsdag 26 juni 2007 @ 23:27:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
function functie(var1, var2)
{
    var oXmlHttp = createXMLHttp();
// knip
}

function onReceived()
{
    if(oXmlHttp.readyState==4)
// knip
}
offtopic:
dit gaat natuurlijk nooit zo werken aangezien oXmlHttp niet binnen de scope van de onReceived functie valt ;)

  • user109731
  • Registratie: Maart 2004
  • Niet online
Erkens schreef op dinsdag 26 juni 2007 @ 23:30:
[...]

offtopic:
dit gaat natuurlijk nooit zo werken aangezien oXmlHttp niet binnen de scope van de onReceived functie valt ;)
Klopt, ik gaf alleen aan hoe zijn code er versimpeld uitziet, en waarom het niet echt een functie in een functie is. Had ik misschien wat duidelijker kunnen vermelden :)

edit: done

Verwijderd

Het geval is dat je een "A"synchroon request doet. Dit betekend dat terwijl jou code verder gaat het resultaat van je request nog niet binnen is.

Heb laatst ook een lange tijd zitten kloten met dit probleem tot de logica tot me door drong.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    function remaining_members(q){
        var XMLHTTPObject = createHTTPHandler();

        if(typeof(XMLHTTPObject) == 'object') {
            XMLHTTPObject.open('POST', 'includes/remaining_members.php', false);
            
            XMLHTTPObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            XMLHTTPObject.setRequestHeader("Content-Length", q.length);
            XMLHTTPObject.setRequestHeader("Connection", "close");                  
            XMLHTTPObject.onreadystatechange=function() {};
            XMLHTTPObject.send('q='+q);                     

      return parseFloat(XMLHTTPObject.responseXML.getElementsByTagName('numleden')[0].childNodes[0].nodeValue);
        }
    };


Dit is een code snippet die wel werkt, hier voor ik een synchroon request uit.

edit: Let op laatste parameter van open() deze is FALSE ipv TRUE.

[ Voor 3% gewijzigd door Verwijderd op 27-06-2007 09:22 ]


  • .Alex
  • Registratie: Augustus 2005
  • Laatst online: 01-08-2022
Verwijderd schreef op woensdag 27 juni 2007 @ 09:21:
Het geval is dat je een "A"synchroon request doet. Dit betekend dat terwijl jou code verder gaat het resultaat van je request nog niet binnen is.

Heb laatst ook een lange tijd zitten kloten met dit probleem tot de logica tot me door drong.

.. code ..

Dit is een code snippet die wel werkt, hier voor ik een synchroon request uit.

edit: Let op laatste parameter van open() deze is FALSE ipv TRUE.
Ik had vannacht ook nog even snel de code in elkaar geprutst en heb deze net vergeleken met die van jou. Ik heb alleen deze regel er niet in staan:
JavaScript:
1
XMLHTTPObject.onreadystatechange=function() {};

Moet deze er eigenlijk wel in nu? En wat doet 'ie?

[ Voor 29% gewijzigd door .Alex op 27-06-2007 10:11 ]


Verwijderd

Hoeft er niet in, laat em er gewoon staan meestal.

  • .Alex
  • Registratie: Augustus 2005
  • Laatst online: 01-08-2022
Verwijderd schreef op woensdag 27 juni 2007 @ 10:26:
Hoeft er niet in, laat em er gewoon staan meestal.
Allright! Thanks!

  • XWB
  • Registratie: Januari 2002
  • Niet online

XWB

Devver
Verwijderd schreef op woensdag 27 juni 2007 @ 09:21:
Het geval is dat je een "A"synchroon request doet. Dit betekend dat terwijl jou code verder gaat het resultaat van je request nog niet binnen is.

Heb laatst ook een lange tijd zitten kloten met dit probleem tot de logica tot me door drong.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    function remaining_members(q){
        var XMLHTTPObject = createHTTPHandler();

        if(typeof(XMLHTTPObject) == 'object') {
            XMLHTTPObject.open('POST', 'includes/remaining_members.php', false);
            
            XMLHTTPObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            XMLHTTPObject.setRequestHeader("Content-Length", q.length);
            XMLHTTPObject.setRequestHeader("Connection", "close");                  
            XMLHTTPObject.onreadystatechange=function() {};
            XMLHTTPObject.send('q='+q);                     

      return parseFloat(XMLHTTPObject.responseXML.getElementsByTagName('numleden')[0].childNodes[0].nodeValue);
        }
    };


Dit is een code snippet die wel werkt, hier voor ik een synchroon request uit.

edit: Let op laatste parameter van open() deze is FALSE ipv TRUE.
Asynchroon en een return value gaat inderdaad niet lukken, het duurde vroeger ook even voor ik doorhad waarom. Maar over synchroon wordt dit gezegd:
Since synchronous usage is rather unsettling, and usually bad taste, you should avoid changing this. Seriously.
Ik heb zelf geen idee waarom.

March of the Eagles


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

Hacku schreef op woensdag 27 juni 2007 @ 18:53:
[...]


Asynchroon en een return value gaat inderdaad niet lukken, het duurde vroeger ook even voor ik doorhad waarom. Maar over synchroon wordt dit gezegd:


[...]


Ik heb zelf geen idee waarom.
Het enige wat ik me kan bedenken is dat dit voorkomt uit het feit dat in sommige browser-implementaties dit zorgt voor een 'lockup' van de GUI zolang als de request duurt, en bij een unresponsive server kan dat wel eens even duren.

Dit is uiteraard een imlementatie issue en geen issue met XHR zelf. Opera heeft er bijvoorbeeld geen last van en in Gran Paradiso (Firefox 3) is het ook al gefixed.

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
crisp schreef op woensdag 27 juni 2007 @ 19:06:
[...]
Het enige wat ik me kan bedenken is dat dit voorkomt uit het feit dat in sommige browser-implementaties dit zorgt voor een 'lockup' van de GUI zolang als de request duurt, en bij een unresponsive server kan dat wel eens even duren.
Maar heb je dezelfde lockup dan niet nog steeds met event-handlers en intervals?

Ik kan me opzich wel voorstellen dat asynchrone requests wat flexibeler en beter uit te breiden zijn...

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

JanDM schreef op woensdag 27 juni 2007 @ 19:46:
[...]

Maar heb je dezelfde lockup dan niet nog steeds met event-handlers en intervals?
Nee, asynchrone requests en ook timers in javascript zijn event-driven. Zolang er geen event is, of geen handler attached aan een bepaald event zal de browser gewoon responsive blijven. Strict genomen is er ook geen reden waarom de browser-GUI niet responsive zou moeten zijn op het moment dat er wel een javascript executiethread actief is; dat is een threading issue van de browser zelf.
Ik kan me opzich wel voorstellen dat asynchrone requests wat flexibeler en beter uit te breiden zijn...
Niet noodzakelijk, qua implementatie zijn synchronous requests vaak zelfs eenvoudiger - je hebt immers meteen de respons voorhanden en in sommige gevallen kan dat zelfs wenselijk zijn.

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
crisp schreef op woensdag 27 juni 2007 @ 22:33:
[...]
Nee, asynchrone requests en ook timers in javascript zijn event-driven. Zolang er geen event is, of geen handler attached aan een bepaald event zal de browser gewoon responsive blijven.
Sorry, stom geformuleerd van mij zie ik achteraf, maar wat ik bedoelde was: heb je ook geen last van trage eventhandlers en uitgestelde timers met synchrone requests? Dus krijg je op die manier ook geen trage UI van je website wanneer je daarvoor bijvoorbeeld events gebruikt? :)

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

JanDM schreef op woensdag 27 juni 2007 @ 22:40:
[...]

Sorry, stom geformuleerd van mij zie ik achteraf, maar wat ik bedoelde was: heb je ook geen last van trage eventhandlers en uitgestelde timers met synchrone requests? Dus krijg je op die manier ook geen trage UI van je website wanneer je daarvoor bijvoorbeeld events gebruikt? :)
Ja, zolang een javascript executiethread actief is zullen alle andere events (en dus ook timers) moeten wachten. Maar like I said: dat is soms ook juist wat je wilt. Als je bijvoorbeeld een ajaxified form-submit doet en het resultaat wilt laten zien dan zou het vreemd zijn als een gebruiker na het submitten nog wijzigingen kan doen (of zelfs opnieuw submitten) nog voordat het eerste request is afgehandeld.
Bij een asynchroon request zou je daar dus allerlei voorzorgsmaatregelen voor moeten treffen.

Er is alleen geen reden waarom de complete browser-GUI zou locken :)

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
crisp schreef op woensdag 27 juni 2007 @ 22:49:
[...]
Maar like I said: dat is soms ook juist wat je wilt. Als je bijvoorbeeld een ajaxified form-submit doet en het resultaat wilt laten zien dan zou het vreemd zijn als een gebruiker na het submitten nog wijzigingen kan doen (of zelfs opnieuw submitten) nog voordat het eerste request is afgehandeld.
In dat geval heb je gelijk, maar stel dat ik op de fp een search query uitvoer, en dat deze door een ajax-request word afgehandeld. De pagina doet er even over om te laden, dus ik besluit gelijk mn tracker instellingen links nog even te wijzigen, of ik open alvast een JS-menu. Dat werkt dan ook niet meer... Maar wanneer data niet dubbel gesubmit mag worden is een synchrone request idd wel handig, daar heb je een punt.
Er is alleen geen reden waarom de complete browser-GUI zou locken :)
Eens :)

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

JanDM schreef op woensdag 27 juni 2007 @ 23:15:
[...]

In dat geval heb je gelijk, maar stel dat ik op de fp een search query uitvoer, en dat deze door een ajax-request word afgehandeld. De pagina doet er even over om te laden, dus ik besluit gelijk mn tracker instellingen links nog even te wijzigen, of ik open alvast een JS-menu. Dat werkt dan ook niet meer...
Maar wanneer data niet dubbel gesubmit mag worden is een synchrone request idd wel handig, daar heb je een punt.
Over het algemeen praat je hier toch over kleine requests die serverside snel afgehandeld kunnen worden, en bij een betrouwbare verbinding zal dat niet snel tot problemen lijden. Op onze frontpage gebruiken we synchrone requests waar dat wenselijk of noodzakelijk is en anders asynchrone requests :)

Intentionally left blank


  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Het hele leuke van de A in AJAX is dat er allerlei requests tegelijkertijd afgehandeld kunnen worden. In december vorig jaar heb ik hierover een artikel geschreven in International PHP-MAG, was een tweeluik over verbetering van betrouwbaarheid van AJAX applicaties op basis van PHP. Eerste artikel gaat over queueing van AJAX requests.

Het artikel heb ik hier even geparkeerd ... wellicht aardig om te lezen. Geen topickaping he ;)

[ Voor 5% gewijzigd door BtM909 op 29-06-2007 10:26 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

gvanh schreef op vrijdag 29 juni 2007 @ 10:12:
Het hele leuke van de A in AJAX is dat er allerlei requests tegelijkertijd afgehandeld kunnen worden. In december vorig jaar heb ik hierover een artikel geschreven in International PHP-MAG, was een tweeluik over verbetering van betrouwbaarheid van AJAX applicaties op basis van PHP. Eerste artikel gaat over queueing van AJAX requests.

Het artikel heb ik hier even geparkeerd ... wellicht aardig om te lezen. Geen topickaping he ;)
Leuk artikel, maar in de basis ben ik het niet met je eens: als volgorde van afhandeling van je requests van belang is dan lijken me synchrone requests het meest voor de hand liggend. Nogmaals: het locken van de browser zelf tijdens synchrone requests is een browser-issue, geen XHR-issue.
Er is wel een reden om asynchrone requests te queuen en dat is het feit dat een browser default maar 2 connecties tegelijkertijd naar dezelfde server kan doen. Als je ervoor zorgt dat je voor asynchrone requests altijd maar 1 connectie gebruikt dan houdt de browser altijd nog een connectie over voor andere requests (laden van plaatjes bijvoorbeeld). Uiteindelijk gebeurd de afhandeling van async request events ook single-threaded, dus daar win je ook niet veel mee met asynchrone requests.

Een queue-wrapper heeft verder nog wel als voordeel dat je ook de tijdsduur van requests kan bijhouden en requests kan cancellen indien nodig (hoewel dat in sommige browsers nog wel eens voor rare effecten kan zorgen, maar ook dat zijn browser-issues) en dat je XHR-objecten kan hergebruiken ipv voor elk request een nieuwe object aan te maken.

Overigens is er op dit moment een formele W3C Working Draft die XHR specificeerd en wordt er al nagedacht over XHR versie 2.

[ Voor 6% gewijzigd door crisp op 29-06-2007 11:00 ]

Intentionally left blank


  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Mijn Queue oplossing was in eerste instantie ingegeven door het feit dat PHP heel vreemd reageerde op twee XMLHttpRequests die (vrijwel) tegelijk verstuurd werden (bijvoorbeeld door twee keer vlak achter elkaar klikken op een knop die een AJAX request doet). PHP reageerde daar in sommige (onvoorspelbare) momenten op door alle sessie-informatie kwijt te raken. Of dit een bug is of een logisch gevolg van een en ander heb ik nooit kunnen achterhalen. Overigens gebruik ik een eigen database-driven sessiehandler, dus met file-access kan het niet te maken hebben gehad.

Met deze oplossing werken mijn (complexe) AJAX applicaties inmiddels probleemloos, dus voor mij was het DE oplossing.

Wat je zegt over het feit dat het een browser issue is, is theoretisch een interessant gegeven, maar helaas zijn we in de praktijk toch gebonden aan de quirks van de verschillende (lees: Internet Explorer) browsers, dus zullen we daar devvers toch rekening mee moeten houden.

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

gvanh schreef op vrijdag 29 juni 2007 @ 12:37:
Mijn Queue oplossing was in eerste instantie ingegeven door het feit dat PHP heel vreemd reageerde op twee XMLHttpRequests die (vrijwel) tegelijk verstuurd werden (bijvoorbeeld door twee keer vlak achter elkaar klikken op een knop die een AJAX request doet). PHP reageerde daar in sommige (onvoorspelbare) momenten op door alle sessie-informatie kwijt te raken. Of dit een bug is of een logisch gevolg van een en ander heb ik nooit kunnen achterhalen.
De default sessionhandler van PHP zorgt er juist voor dat je geen race condition krijgt doordat de sessionfile exclusief gelocked wordt, daardoor moeten je requests ook op elkaar wachten. Je kan dus in principe geen session info kwijt raken, tenzij je op meerdere plaatsen in je code de sessie opent en sluit.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

gvanh schreef op vrijdag 29 juni 2007 @ 12:37:
[...]
Wat je zegt over het feit dat het een browser issue is, is theoretisch een interessant gegeven, maar helaas zijn we in de praktijk toch gebonden aan de quirks van de verschillende (lees: Internet Explorer) browsers, dus zullen we daar devvers toch rekening mee moeten houden.
Dat is een afweging die je zelf moet maken. Rekening houden met is in mijn boek iets anders dan koste wat het kost om alle quirks heen zien te werken, zeker als het gaat om een issue die slechts sporadisch op zal treden :)

Intentionally left blank

Pagina: 1