Avatar billede Xranoz Nybegynder
12. oktober 2009 - 18:22 Der er 13 kommentarer og
1 løsning

Problemer med brug af array

Hej

Jeg har siddet og arbejdet med følgende funktion. Jeg har problemer med at få returneret arrayet korrekt, så det kan benyttes udenfor funktionens "rammer". Hvad gør jeg for at løse problemet? Kan nogen give et eksempel på hvordan de returneres korrekt og hvordan man derefter kan udskrive en plads i arrayet.

På forhånd tak!

function createWaypoints() {
        var waypoints = new Array();
        downloadUrl("data.xml", function(data) {
            var xml = parseXml(data);
            var markers = xml.documentElement.getElementsByTagName("marker");
                for (var i = 0; i < markers.length; i++) {
                    var point = '"' + parseFloat(markers[i].getAttribute("lat")) + ',' + parseFloat(markers[i].getAttribute("lng")) + '"';
                    waypoints[i] = point;
                    //document.write(waypoints[i]);
                }
        });
        return waypoints;
    }
Avatar billede tjens Nybegynder
12. oktober 2009 - 20:54 #1
Det må være et scope problem, fordi du definerer en ny inline funktion.

Prøv at lave en alert(waypoints); lige før return.
Så tror jeg du vil se, at den er tom på det tidspunkt.
Avatar billede Xranoz Nybegynder
12. oktober 2009 - 21:50 #2
Men hvad gør jeg så?
Avatar billede tjens Nybegynder
12. oktober 2009 - 21:59 #3
Definerer den globalt, og undlader return af den.

D.v.s. flytter linien var waypoints = new Array(); uden for function. Og derudover får den tømt/nulstillet på rette steder, hvis den fyldes flere gange i scriptet.
Avatar billede Xranoz Nybegynder
12. oktober 2009 - 22:05 #4
Jeg har forsøgt mig med at have arrayet globalt, men syntes ikke at kunne få det til at virke. Måske har det noget at gøre med det at tømme / nulstille. Jeg vil meget gerne acceptere dit svar, men har brug for hjælp til at vide hvordan jeg nulstiller arrayet de rigtige steder.
Avatar billede tjens Nybegynder
12. oktober 2009 - 22:15 #5
Det vigtige er, at der kun findes 1 forekomst af

  var waypoints;

i hele scriptet.

Nulstilling kan du bibeholde der hvor den før var defineret, ved at skrive:

    waypoints = new Array();

Jeg kender ikke flowet i dit script, så jeg ved ikke om du kalder
createWaypoints() flere gange.

PS: Hvor kommer data fra i din kode i spørgsmålet? Er den også globalt defineret?
Avatar billede Xranoz Nybegynder
12. oktober 2009 - 23:03 #6
Her er hele scriptet. Jeg håber det kan kaste lidt mere lys over problemet:

<script type="text/javascript">

    function createWaypoints() {
        var waypoints = new Array();
        downloadUrl("data.xml", function(data) {
            var xml = parseXml(data);
            var markers = xml.documentElement.getElementsByTagName("marker");
                for (var i = 0; i < markers.length; i++) {
                    var point = '"' + parseFloat(markers[i].getAttribute("lat")) + ',' + parseFloat(markers[i].getAttribute("lng")) + '"';
                    waypoints[i] = point;
                }
        });
        return waypoints;
    }
    document.write(createWaypoints());
       
        function downloadUrl(url, callback) {
            var request = window.ActiveXObject ?
                new ActiveXObject('Microsoft.XMLHTTP') :
                new XMLHttpRequest;

                request.onreadystatechange = function() {
            if (request.readyState == 4) {
                request.onreadystatechange = doNothing;
                callback(request.responseText, request.status);
            }
        };

                request.open('GET', url, true);
                request.send(null);
        }

        function parseXml(str) {
            if (window.ActiveXObject) {
                var doc = new ActiveXObject('Microsoft.XMLDOM');
                doc.loadXML(str);
                return doc;
        }    else if (window.DOMParser) {
                return (new DOMParser).parseFromString(str, 'text/xml');
            }
        }
        function doNothing() {}
</script>
Avatar billede ebusiness Nybegynder
12. oktober 2009 - 23:12 #7
Lidt kludret konstruktion med en funktion inde i en anden, normalt prøver jeg på at undgå den slags.

Jeg går ud fra at downloadUrl er en wrapper omkring en funktion som henter data fra en fil på din server. Det inkluderer normalt at man bryder kodeflowet når forespørgslen er sendt og venter på svaret. Du bryder ikke flowet i den funktion der. Så jeg vil tro at din fejl er så grundlæggende som at du ikke har forstået metoden helt rigtigt.

Efter at olebole har frarådet W3schools's AJAX guide prøver jeg at linke til en anden i stedet: http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
Avatar billede tjens Nybegynder
12. oktober 2009 - 23:22 #8
Med ændringer for at få variabel waypoints til at blive global og undgå scope problemer:

<script type="text/javascript">
    var waypoints;
    function createWaypoints() {
        waypoints = new Array();
        downloadUrl("data.xml", function(data) {
            var xml = parseXml(data);
            var markers = xml.documentElement.getElementsByTagName("marker");
                for (var ix = 0; ix < markers.length; ix++) {
                    var point = '"' + parseFloat(markers[ix].getAttribute("lat")) + ',' +            parseFloat(markers[ix].getAttribute("lng")) + '"';
                    waypoints[ix] = point;
                }
        });

    }

    function downloadUrl(url, callback) {
        var request = window.ActiveXObject ?
        new ActiveXObject('Microsoft.XMLHTTP') :
        new XMLHttpRequest;
        request.onreadystatechange = function() {
          if (request.readyState == 4) {
            request.onreadystatechange = doNothing;
            callback(request.responseText, request.status);
          }
        };
        request.open('GET', url, true);
        request.send(null);
    }

    function parseXml(str) {
        if (window.ActiveXObject) {
            var doc = new ActiveXObject('Microsoft.XMLDOM');
            doc.loadXML(str);
            return doc;
    }    else if (window.DOMParser) {
            return (new DOMParser).parseFromString(str, 'text/xml');
        }
    }
    function doNothing() {}

    createWaypoints()
    document.write(waypoints);
       
</script>

Jeg synes desuden, at strukturen i scriptet er lidt indviklet: Er det lavet efter devisen Hvis det var svært at lave, skal det også være svært at forstå?  ;-)

Eller er det noget du har kopieret fra nettet og bygget videre på?
Avatar billede Xranoz Nybegynder
12. oktober 2009 - 23:47 #9
Tak for gennemgangen, synes dog stadig ikke at der bliver udskrevet noget. Du har fuldstændig ret i at det er taget fra nettet og jeg så har ændret i det. Det hænger sammen med at jeg er fuldstændig nybegynder og intet ved om det. Derfor er jeg også havnet i den her situation, hvor jeg ikke aner hvad jeg skal gøre :)
Avatar billede tjens Nybegynder
12. oktober 2009 - 23:55 #10
Jeg skal i seng nu, men hvis du har energi til mere, så prøv at studere løsningen her:

http://www.eksperten.dk/spm/888250#reply_7462080

Det minder meget om dit, hvor der indlæses en xml-fil, som der trækkes felter ud fra.

Måske du skulle skrive dit script om med udgangspunkt i den.
Avatar billede ebusiness Nybegynder
13. oktober 2009 - 00:01 #11
Det dur stadigvæk ikke tjens, funktionen som opretter waypoints bliver først kaldt når svaret kommer, men koden kører videre til document.write(waypoints); før da.

Ud med document.write, det er ikke en specielt genial funktionalitet til at begynde med, men jeg tror slet ikke at vi kan få den til at virke i denne sammenhæng. I stedet skal vi bruge en container til at skrive indholdet i, fx en div, og så kan innerHTML bruges til at fylde den.

<div id="tomdiv"></div>
<script type="text/javascript">
    var waypoints;
    function createWaypoints() {
        waypoints = new Array();
        downloadUrl("data.xml", function(data) {
            var xml = parseXml(data);
            var markers = xml.documentElement.getElementsByTagName("marker");
                for (var ix = 0; ix < markers.length; ix++) {
                    var point = '"' + parseFloat(markers[ix].getAttribute("lat")) + ',' +            parseFloat(markers[ix].getAttribute("lng")) + '"';
                    waypoints[ix] = point;
                }
            document.getElementById("tomdiv").innerHTML=waypoints;
        });

    }

    function downloadUrl(url, callback) {
        var request = window.ActiveXObject ?
        new ActiveXObject('Microsoft.XMLHTTP') :
        new XMLHttpRequest;
        request.onreadystatechange = function() {
          if (request.readyState == 4) {
            request.onreadystatechange = doNothing;
            callback(request.responseText, request.status);
          }
        };
        request.open('GET', url, true);
        request.send(null);
    }

    function parseXml(str) {
        if (window.ActiveXObject) {
            var doc = new ActiveXObject('Microsoft.XMLDOM');
            doc.loadXML(str);
            return doc;
    }    else if (window.DOMParser) {
            return (new DOMParser).parseFromString(str, 'text/xml');
        }
    }
    function doNothing() {}

    createWaypoints()

</script>
Avatar billede Xranoz Nybegynder
13. oktober 2009 - 02:08 #12
Tak for svaret begge to! Tjens: Jeg kunne sikkert godt skrive min kode om ud fra dit eksempel. Ebusiness: Dit eksempel virker, men jeg skal bruge arrayet i forbindelse med en anden funktion (til at tegne en rute på et Google Map), er der nogen måde hvorpå jeg kan bruge din kode til at returnere et array jeg kan bruge i en anden funktion?
Avatar billede ebusiness Nybegynder
13. oktober 2009 - 13:03 #13
Dine data kommer til at ligge i det globale array waypoints, men først når svaret fra serveren er kommet.

Du kan lægge kode som reagerer lige efter document.getElementById("tomdiv").innerHTML=waypoints;

Eller du kan på et senere tidspunkt simpelthen tjekke om der er data i arrayet: if(waypoints.length) og så vente hvis det er tomt.
Avatar billede tjens Nybegynder
13. oktober 2009 - 21:31 #14
Jeg har nu lavet en version af dit script, hvor der er tilføjet nogen statuslinier som vises på skærmen.

Så kan vi se hvornår de forskellige programstumper kører i forhold til hinanden:
http://tjens.dk/eksperten/889291/index.html

De linier der starter med 1.2.3 er nummereret efter hvordan du og jeg gerne ville have scriptet til at køre.

Men i praksis kommer der til at stå 2.3.1, og dermed er xml-filen ikke hentet ind endnu, der hvor scriptet forsøger at bruge data.

Jeg har tilføjet et delay, og herefter er arrayet faktisk returneret!
(Jeg viser ikke hele koden her: højreklik på siden fra linket ovenfor for at se source.)

Men konklusionen må være at du er nødt til vende dig til tanken om at scriptet kører videre, selv om svaret fra xml-filen ikke er kommet endnu.

Dermed skal designet være event-styret: Koden skal ikke fortsætte med næste opgave før svaret foreligger. Strukturen i eksemplet i #10 synes jeg er nemmere at overse, men det er måske fordi jeg altid laver det på denne måde.

Hvis du bibeholder din programstruktur, skal du kalde rutinen. der behandler data i arrayet, der hvor linien, der skriver 1, findes i eksemplet. Så må du overføre arrayet som parameter, i stedet for at returnere det.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester

IT-JOB

Csis Security Group A/S

Sales Executive

IT-Forsyningen I/S

It-specialist til serverteam

Politiets Efterretningstjeneste

Datacentertekniker hos PET

Capgemini Danmark A/S

Finance Lead (SAP)