Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[js/jQuery/ajax] Waarde meegeven aan callback

Pagina: 1
Acties:

  • Sando
  • Registratie: Januari 2007
  • Niet online

Sando

Sandoichi

Topicstarter
Als je de titel leest lijkt het zo simpel, maar ik loop me toch een tijd te verspillen..

Ik wil wat informatie van een aantal webservers halen waarbij loading textje verschijnt (zoals bij google webapps). Alleen ik wil voor iedere server een apart balkje, waarmee iets gebeurt afhankelijk van of de request goed of fout gaat.

Dat lukt allemaal prima, behalve dat de anonieme functies in de ajax-request-callbackfuncties de waardes pas overnemen als ze aan de beurt zijn, waardoor reqGood() of reqBad() altijd de laatste reqId waarde aanspreken in plaats van de waarde die reqId had op het moment dat het ajax request werd gemaakt.

Ik hoop dat bovenstaand verhaal duidelijk is icm een stukje code:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(...)
    for (var n=0; n<servers.length; n++) {
        var reqId = "request"+n; // id van request - for $ selector
        var reqSrv = servers[n]; // request server

        // Add load msg
        $("#msgContainer").append($("<div id=\""+reqId+"\"><span>Loading from "+reqSrv+"</span></div>"));

        // Do the requests
        $.ajax({
            url: servers[n],
            data: "ajaxrequest=true",
            dataType: "xml",
            success: function(rXML){reqGood(rXML,reqId);},
            error: function(r,s,e){reqBad(r,s,e,reqId,reqSrv);} // Waardes zijn dynamic tot functie, niet goed!
        });
    }


Kortom, maakt niet uit welke van alle berichtjes goed of fout gaat, de goed of fout functie wordt altijd toegepast op het laatste berichtje. Niet goed.

Ik dacht het eerst te fixen met een array om elke nieuwe id in een array te stoppen, maar de index n is uiteraard ook uitgeteld in de callback. De volgende optie leek eval(), maar dat is niet te gebruiken in een object. Althans ik kreeg niets voor elkaar.

Het laatste wat misschien zou helpen is om handmatig een variabele aan het xmlHttpRequest object mee te geven via $.ajax beforeSend, omdat dat object ook mee wordt gegeven in de succes/error functies, waardoor ik deze in de callback weer kan terughalen. Is dat mogelijk? Of heeft iemand een ander idee?

🇪🇺 Buy from EU (GoT)


  • Sando
  • Registratie: Januari 2007
  • Niet online

Sando

Sandoichi

Topicstarter
note:
Die functies met (r,s,e) enzo lijken mss sneaky maar het zijn gewoon de jQuery standaard argumenten die ik even afkort.

jQuery documentatie:
error Function
A function to be called if the request fails. The function gets passed three arguments: The XMLHttpRequest object, a string describing the type of error that occurred and an optional exception object, if one occurred. This is an Ajax Event.
JavaScript:
1
2
3
4
5
function (XMLHttpRequest, textStatus, errorThrown) {
  // typically only one of textStatus or errorThrown 
  // will have info
  this; // the options for this ajax request
}

[ Voor 28% gewijzigd door Sando op 27-02-2008 14:34 ]

🇪🇺 Buy from EU (GoT)


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 20:57

crisp

Devver

Pixelated

apart scopen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function createSuccessFunction(reqId)
{
  return function(rXML)
  {
    reqGood(rXML, reqId);
  }
}

function createErrorFunction(reqId, reqSrv)
{
  return function(r, s, e)
  {
    reqBad(r, s, e, reqId, reqSrv);
  }
}

$.ajax({
  // ...
  success: createSuccessFunction(reqId),
  error: createErrorFunction(reqId, reqSrv)
});

Intentionally left blank


  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

crisp schreef op woensdag 27 februari 2008 @ 14:35:
apart scopen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function createSuccessFunction(reqId)
{
  return function(rXML)
  {
    reqGood(rXML, reqId);
  }
}

function createErrorFunction(reqId, reqSrv)
{
  return function(r, s, e)
  {
    reqBad(r, s, e, reqId, reqSrv);
  }
}

$.ajax({
  // ...
  success: createSuccessFunction(reqId),
  error: createErrorFunction(reqId, reqSrv)
});
Ok, hier snap ik dus geen reet van nog :X hoe weet die function die gereturned wordt waarmee zn parameter gevuld gaat worden :?

Stop uploading passwords to Github!


Verwijderd

De waarde weet ie nog niet, maar de pointer naar de waarde wordt door de scoping behouden. Die regId wordt later wel weer ingevuld.

Alle variabelen gedeclareerd binnen een functie zijn ook beschikbaar binnen een functie die in die functie zijn gedeclareerd.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 20:57

crisp

Devver

Pixelated

Zelf gebruik ik voor dit soort dingen bind() (geleent uit prototype.js):
JavaScript:
1
2
3
4
5
6
7
8
9
Function.prototype.bind = function()
{
    var handler = this, args = Array.slice(arguments, 0), obj = args.shift();

    return function()
    {
        return handler.apply(obj, args.concat(Array.slice(arguments, 0)));
    }
}

(deze gebruikt ook Array generics)

Dat zou dan dit worden:
JavaScript:
1
2
3
4
5
$.ajax({
  // ...
  success: reqGood.bind(this, reqId),
  error: reqBad.bind(this, reqId, reqSrv)
});

De eerste parameter is eventueel een scope waarin de functie moet worden uitgevoerd.
Note dat je in je handler functies wel eerst je eigen parameters krijgt en dan pas overige argumenten.

Intentionally left blank


Verwijderd

ik vind het iha een slecht idee om bestaande objecten uit te breiden, je kan dan behoorlijk in de knoop komen als iemand anders (wellicht een nieuwe js versie) ook een uitbreiding doet onder dezelfde naam met een net iets andere functionaliteit,

dus nee tegen Object.prototype.extend, Array.prototype.watdanook en Function.prototype.bind

waarom maak je niet een afgeleid object en hang je daar je nieuwe methods aan, zoals mensen altijd al gewend zijn in andere talen?
je kan dan niet meer gebruik maken van {} en [] declaraties, mja, boeie

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 20:57

crisp

Devver

Pixelated

Verwijderd schreef op donderdag 28 februari 2008 @ 19:06:
ik vind het iha een slecht idee om bestaande objecten uit te breiden, je kan dan behoorlijk in de knoop komen als iemand anders (wellicht een nieuwe js versie) ook een uitbreiding doet onder dezelfde naam met een net iets andere functionaliteit,

dus nee tegen Object.prototype.extend, Array.prototype.watdanook en Function.prototype.bind
Daar ben ik het niet mee eens. De mogelijkheid om native objecten in javascript te extenden is wat het onder andere zo'n krachtige taal maakt. Zo hoef je geen eigen objecten aan te maken om bijvoorbeeld nieuwe features te 'backporten' naar oudere implementaties, denk bijvoorbeeld aan javascript array-methods zoals slice() (niet ondersteund in bijvoorbeeld IE <= 5.0) of meer recent de handige javascript 1.6 methods als indexOf() en lastIndexOf() en de iteratieve methods.

Ik ben het met je eens dat het prototypen van Object in de meeste gevallen onnodig is en zelfs voor problemen kan zorgen in scripts die niet defensief genoeg omgaan met properties in iteraties, maar voor de rest zijn er genoeg redenen om juist wel de kracht van prototyping op primatives te gebruiken.

Uiteraard dien je daar zelf ook defensief mee om te gaan; in fact, ik gebruik een non-overriding extend() functie om prototyped methods toe te kennen (mijn voorbeeld hier was ook slechts een voorbeeld, geen complete implementatie). Verder is het gewoon een kwestie van een (al dan niet eigen) idioom volgen en gewoon niet verschillende libraries tesamen gebruiken en van 3rd party snippets altijd weten wat ze precies doen. Verder denk ik niet dat nieuwere versies javascript ineens een bind() method gaan toevoegen aan het Function object die iets anders zou doen dan bijvoorbeeld de huidige bind() in prototype.js - de mensen die specificaties maken kijken zelf ook eerst naar real-world use-cases en maken afwegingen op basis van potentiele breakage.
waarom maak je niet een afgeleid object en hang je daar je nieuwe methods aan, zoals mensen altijd al gewend zijn in andere talen?
je kan dan niet meer gebruik maken van {} en [] declaraties, mja, boeie
Tsja, waarom zou je niet de eigenschappen van een taal gebruiken? Wat is het argument in "omdat we dat gewend zijn in andere talen"? Javascript is javascript, geen java of ruby of python (al zouden veel mensen dat blijkbaar wel willen).

Enige sidenote die ik zou willen maken en waar ik je dus een klein beetje in tegemoed kom; het is net als met alles: overdaad schaadt. Het is overkill om een method aan een primitive object te hangen voor 1 simpele usecase in je script, maar een aantal gevallen rechtvaardigen het wel degelijk - zie bijvoorbeeld mijn opmerking over de Array extra's van javascript1.6, en imo valt bind() er ook onder ;)

Intentionally left blank


  • Sando
  • Registratie: Januari 2007
  • Niet online

Sando

Sandoichi

Topicstarter
Hey crisp bedankt voor de twee oplossingen!
Wat je doet met bind, wist niet eens dat dat mogelijk was. Dat apart scopen vind ik in dit geval de netste oplossing. Moeten de functies in create(...) gereturned worden?

Beetje jammer (maar waarschijnlijk wel goed) dat ik er op het aller aller laatst achter kom dat browsers niet willen dat je externe servers gaat ajaxen, maar intern werkt het allemaal prima.

🇪🇺 Buy from EU (GoT)


  • Alex)
  • Registratie: Juni 2003
  • Laatst online: 18-11 20:57
Dat je geen externe servers kunt benaderen klopt, dat heeft te maken met een securitybarrière. Wat je zou kunnen doen is je requests proxy'en via een lokaal script.

We are shaping the future

Pagina: 1