• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[GELÖST] XMLHttpRequest in prototype?

terra75

Member
Hallo !

Ich versuche hier grade eine JSON Datei zu öffnen und danach direkt weiter zu verarbeiten.
Mit der Methode this.xobj.open('GET', this.root + this.jsonFile, false); funktioniert es auch ganz gut. Allerdings bekomme ich in der Development Console eine Warnung, das Synchrone Abfragen Veraltet sind.
Nun gut, dann setze ich halt in der open Anweisung das false auf true und schon beginnen die Probleme.

Hier mal der Code im Prototype.
PHP:
	loadJsonFile2 : function (callback) {	
		var _this = this;
		
		this.root = document.location.toString();		
		this.xobj = new XMLHttpRequest();
		
		if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
			this.xobj.setRequestHeader("Content-Type", "application/json");
		} else {
			if (this.xobj.overrideMimeType)
				this.xobj.overrideMimeType("application/json");
		};
	
		this.xobj.onreadystatechange = function () {
			if ( _this.xobj.readyState == 4 && _this.xobj.status == 200 ) {
				return _this.xobj.responseText;
				//_this.xobj.callback = _this.xobj.responseText;
			};
		};
	
		this.xobj.open('GET', this.root + this.jsonFile + '?t=' + Math.random(), true);
		this.xobj.send();
	},

An anderer Stelle im Prototype wird der Loader wie folgt aufgerufen:
PHP:
initialize : function() {		
		this.createLoaderScreen();
	
		this.jsonLoadedFile = this.loadJsonFile2();
		console.log(this.jsonLoadedFile);
		this.jsonData = JSON.parse(this.jsonLoadedFile);

Allerdings bekomme ich in der Console ein undefined heraus.
Was mache ich falsch?

Gruß, Terra
 
Zuletzt bearbeitet von einem Moderator:
Allerdings bekomme ich in der Console ein undefined heraus.
loadJsonFile2 gibt auch nichts zurück, deswegen ist jsonLoadedFile auch undefined
Was mache ich falsch?
loadJsonFile2 hat bei dir einen parameter callback. dieses callback rufst du weder auf, noch übergibst du es an die funktion
alternative zum callback: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise
 
OK, hab es damit hinbekommen. Was für eine Fummelarbeit. :D

Für diejenigen, die es auch mal benötigen:
PHP:
loadJsonFile : function (url) {	
		
		return new Promise( function(callback, reject) {
					
			var root = document.location.toString();			
			var xobj = new XMLHttpRequest();
			
			if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
				xobj.setRequestHeader("Content-Type", "application/json");
			} else {
				if (xobj.overrideMimeType)
					xobj.overrideMimeType("application/json");
			};
		
			xobj.onreadystatechange = function () {
				if ( xobj.readyState == 4 && xobj.status == 200 ) {
					callback(xobj.responseText);
				};
			};
		
			xobj.open('GET', root + url + '?t=' + Math.random(), true);
			xobj.send();
			
		});
		
	},

Und der dazugehörige Aufruf:
PHP:
initialize : function() {	
		var _this = this;
	
		this.createLoaderScreen(); // ignorieren

		this.loadJsonFile( this.jsonFile ).then(function(response) {
			
			_this.jsonData = JSON.parse(response);
						
			for (var i=0; i < Object.keys(_this.jsonData).length; i++) {
               // Daten von Json werden an anderer Stelle weiterverarbeitet.
				_this.fileToLoad.push({key:_this.jsonData[i].key, name:_this.jsonData[i].name, path:_this.jsonData[i].path });  
			}
			
			_this.start();  // ignorieren
			
		});
	},

Gibt es da noch etwas zu verbessern oder ist die Funktion allgemein schon gut? Wenn schon, denn schon ! :)

Danke,
Terra
 
if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) der userAgent sagt nichts aus
xobj.setRequestHeader("Content-Type", "application/json"); warum ist der request-contenttype json, wozu soll das gut sein?
xobj.overrideMimeType("application/json"); wozu das? das ist aufgabe des servers
function(callback, reject) reject sollte dann im fehlerfall auch gerufen werden
var _this = this; das ist geschmackssache, mir gefällt https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function/bind besser
sollte loadJsonFile nicht eine private funktion sein?
 
sollte loadJsonFile nicht eine private funktion sein?
In wie fern meinst du das? Sorry, my Javascript is not so fine. :)

reject sollte dann im fehlerfall auch gerufen werden
Wird noch gemacht. Mir war es grade nur wichtig, das es überhaupt funktioniert.

Bei den restlichen Sachen, die du angemerkt hast habe ich mich von anderen Seiten inspirieren lassen, wo dieses so dargestellt wurde. Hat für mich auch Sinn ergeben, da ich ja ein JSON File aufrufe.

Und mit dem _this. Ich finde es einfach komfortabler, das so zu schreiben als mit .bind(this).

Terra
 
Zuletzt bearbeitet:
Du meinst also eine normale Funktion innerhalb der Initialize function()?
Wie gesagt, bin noch nicht so konform mit solch einer "komplexen" Programmierung in JS. Und scope musste ich erstmal nachgoogeln :D

Natürlich würde das gehen, da die loadJsonFile Funktion genau nur 1x für eine Datei aufgerufen wird. So viel Gedöns, wegen einer einzigen Json Datei. Aber höre mir gerne Vorschläge von dir (und anderen) an.

Terra
 
Ich würde ja ein Framework das XHR machen lassen...

PS: Du must auch bei einem XHR nicht unbedingt absolute Pfade angeben. Wie bei Bildern etc. kannst du da auch relative Pfade verwenden. Ist robuster als dein Ansatz mit dem root. Wenn du nämlich irgendwann mal den Query- oder Hash-Teil der URL nutzen möchtest, musst du deine Funktion umschreiben.
 
Ich würde ja ein Framework das XHR machen lassen...

PS: Du must auch bei einem XHR nicht unbedingt absolute Pfade angeben. Wie bei Bildern etc. kannst du da auch relative Pfade verwenden.

Also ein extra Framework zu benutzen um nur eine Datei zu laden finde ich ein wenig übertrieben. JQuery würde sich da natürlich anbieten aber möchte so wenig wie möglich mit weiteren Frameworks arbeiten. Zum anderen lerne ich ja auch, wenn ich das selbst erstelle. :)

Das mit dem root war jetzt nur ein Test. Schlussendlich wird am Anfang noch eine Config.js geladen, wo alle Pfade, die wichtig sind bereits vordefiniert werden.

Im Moment sieht die ganze Funktion wie folgt aus:
PHP:
initialize : function() {	
		var _this = this;
		
		this.createLoaderScreen();
		
		function loadJsonFile(url) {			
			return new Promise( function(resolve, reject) {
							
				var xhr = new XMLHttpRequest();

				xhr.onload = function() { // xhr.onreadystatechange for all browser				 
					if ( xhr.readyState == 4 && xhr.status == 200 ) {					
						resolve( xhr.response );
					} else {
						reject( console.error(xhr.statusText) );
					}
				};

				xhr.open('GET', url + '?t=' + Math.random(), true);
				xhr.send();
				
			});
		};
	
		loadJsonFile( this.jsonFile ).then( function(response) {
	
			var jsonData = JSON.parse(response);
						
			for (var i=0; i < Object.keys( jsonData ).length; i++) {
				_this.fileToLoad.push({ key: jsonData[i].key, name: jsonData[i].name, path: jsonData[i].path });
			}
			
			_this.start();			
		});
	},
Ist sicherlich noch Verbesserungswürdig aber sie funktioniert im Moment auf den gängigsten Browsern.

PS: Wie markiere ich den Topic als "Beantwortet"?


Gruß, Terra
 
Also ein extra Framework zu benutzen um nur eine Datei zu laden finde ich ein wenig übertrieben.
Stimmt, aber ein Framework kann ja meist noch mehr...
Zum anderen lerne ich ja auch, wenn ich das selbst erstelle.
Schon - du kannst dir ja auch selbst zu Lernzwecken ein kleines Framework basteln.
Im Moment sieht die ganze Funktion wie folgt aus:
Sieht ganz OK aus... nur
Object.keys( jsonData ).length
ist irgendwie seltsam. Ist jsonData ein Array oder ein Objekt? Bei einem Array würde sich ARRAY.forEach() anstatt der Schleife anbieten.
Wie markiere ich den Topic als "Beantwortet"?
Das kann anscheinend nur ein Moderator/Admin machen - ich hab' das mal für dich gemacht.
 
Schon - du kannst dir ja auch selbst zu Lernzwecken ein kleines Framework basteln.
Sowas in der Art mache ich ja grade. Es ist zwar kein Framework aber ein kleines Spiel mit THREE.js.
Das, was ich hier jetzt Besprochen habe, gehört zum Teil zu einem Preloader, der Texturen, die in einer separaten Json Datei definiert sind vorzuladen und als verarbeitetes Array an das Hauptprogramm weiterleitet.

Finde das ganze als guten Einstieg in die Objektorientierte Programmierung. Bis jetzt hab ich immer Spagetticode niedergerasselt. Hat zwar auch immer sein Zweck erfüllt aber wenn man nach einem halben Jahr da nochmal dran gegangen ist, hat man nichts mehr im Code wiedergefunden. :D

Ist jsonData ein Array oder ein Objekt?
jsonData schmeißt mir nur Object aus. Also mehrere unbenannte Objects.
Von daher viel die Wahl bei mir auf Object.keys( jsonData ).length;.


ich hab' das mal für dich gemacht.
Danke !



Terra
 
Zurück
Oben