在第一个功能完成后启动第二个功能。

时间:2015-03-21 17:30:53

标签: jquery ajax jquery-deferred

我遇到了jQuery& amp; AJAXs。

我有2个函数,做一些AJAX - Stuff:

1

getSelectedRoom($chosenRoom) 

2:

getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom)

第一个Function创建一个div并插入一个图像。现在,当这个完成时,我需要该div的高度与里面的图像。因此我需要第二个函数等待,直到第一个函数完成所有操作。

我认为以下代码可以解决我的问题,但第二个函数有时启动,bevor div准备就绪并获得0px的高度。

$.when( 
    // Wohnungsgrundriss anzeigen
    getSelectedRoom($chosenRoom) 

).done(
    // Device Tablle mit allen verfügbaren Geräten füllen.
    getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom)

);

在功能2开始之前,有没有办法确保功能1已经完成?

以下是这些功能的代码:

function getSelectedRoom($chosenRoom){
// Ausgewählten Raum mit platzierten Geräten anzeigen
	// Raumgrundriss laden
	$.post("getSelectedRoom.php", {chosenRoom : $chosenRoom},
		function($echoData){
			$("div#SelectedRoom").html($echoData);
			$(".droppable").droppable({
				// Nur Objekte die komplett drin sind werden akzeptiert.
				tolerance: "fit",

				// Funktionsaufruf wenn ein Gerät in das Bild gedropt wird.
				drop: function( event, ui ){
					var $parent = ui.draggable;
					var $draggedElement = $(ui.draggable);
					var $dropZone = $(this);

					// Berechnen der Position relativ zum Zimmergrundriss (als absolute Werte in Px)
					var $leftOffset = $parent.offset().left - $dropZone.offset().left;
					var $topOffset = $dropZone.offset().top - $parent.offset().top;

					// Umrechnen der absoluten Werte zu prozentualen Werten, abhängig vom Zimmergrundriss (Zimmergrundriss = 1000%)
						// Grundrissgröße bestimmen
						var $groundplotWidth = $("div#SelectedRoom").width();
						var $groundplotHeight = $("div#SelectedRoom").height();

						// Umrechnung in %
						$leftOffset = Math.round($leftOffset * ( 1000 / $groundplotWidth ));
						$topOffset = Math.round($topOffset * ( 1000 / $groundplotHeight ));

					//Speichern der Position in der MySQL Tabelle
					$.post("insertDevice.php", {chosenRoom : $chosenRoom, ID : $(ui.draggable).attr('id') , X : $leftOffset, Y : $topOffset},
						function($echoData){
							// Platzhalter für eventuelle Bestätigung nach dem erfolgreichen speichern...
							console.log($echoData);
						});

					// Debugging:
					console.log(".....................");
					console.log(".Einfügen............");
					console.log("chosenRoom: " + $chosenRoom);
					console.log("ID: " + $(ui.draggable).attr('id'));
					console.log("X: " + $leftOffset);
					console.log("Y: " + $topOffset);
					console.log(".....................");

				},
				// Funktionsaufruf wenn ein Gerät aus dem Bild gedropt (war zuvor im Bild) wird.
				out: function( event, ui ){
					$.post("delDevice.php", {chosenRoom : $chosenRoom, ID : $(ui.draggable).attr('id')}, 
						function($echoData){
							// Platzhalter für eventuelle Bestätigung nach dem erfolgreichen löschen...

							// Debugging:
							console.log(".....................");
							console.log(".Entfernen...........");
							console.log("chosenRoom: " + $chosenRoom);
							console.log("ID: " + $(ui.draggable).attr('id'));
							console.log(".....................");
							console.log($echoData);

						});
				}
			});
		});
}

function getDeviceTable($tbl, $target, $splt_id, $splt_zustand, $splt_name, $splt_bedienel, $noText, $chosenRoom){
	if ( $tbl == "all" ) {								// Abfrage für alle Tabellen

		$text =  	'<p>Wählen Sie eine Tabelle um die darin enthaltenen Geräte zu bearbeiten.</p>';
		$print = 	'<p id="tblCON"></p>' + 
					'<p id="tblFUN"></p>' + 
					'<p id="tblSEN"></p>';
		
		if($noText != 1){			
			$print = $text + $print;
		};

		$($target).html($print);

		// Beide AJAX Calls werden lsogeschickt. then() wird ausgeführt, wenn beide Callbacks durchgeführt wurden.
		$.when(
			getDeviceTable("CONNECTION", "p#tblCON", $splt_id, $splt_zustand, $splt_name, $splt_bedienel, $noText, $chosenRoom),
			getDeviceTable("FUNK", "p#tblFUN", $splt_id, $splt_zustand, $splt_name, $splt_bedienel, $noText, $chosenRoom)
		).done( positionDevices($chosenRoom) );

		if($noText  != 1){
			getDeviceTable("SENSOR", "p#tblSEN", $splt_id, $splt_zustand, $splt_name, $splt_bedienel);	
		}
		
	} else {											// Abfrage für einzelne Tabelle
		$.post("getDeviceTable.php", {tbl : $tbl, splt_id : $splt_id, splt_zustand : $splt_zustand, splt_name : $splt_name, splt_bedienel : $splt_bedienel, noText : $noText,
		}, function($echoData){
			// Ausgabe der Tabelle im Targetbereich
			if($noText != 1){	
				if ($tbl == "CONNECTION") {
					$echoData = '<h3>Digitale Ein- & Ausgänge</h3>' + $echoData;
				} else if ($tbl == "FUNK") {
					$echoData = '<h3>Funkschalter & -Steckdosen</h3>' + $echoData;
				} else if ($tbl == "SENSOR") {
					$echoData = '<h3>Temperatursensoren</h3>' + $echoData;
				} else {
					alert("Die Tabelle \"" + $tbl + "\" ist der Funktion getDeviceTable() nicht bekannt!");
				}
			}
			
			if($noText == 1){
			// Ausgabe als aufgeklappte Tabellen
				$($target).html('').append($echoData).fadeOut(0).fadeIn(500);
			// Drag & Drop in der Zimmerverwaltung:
				$(".draggable").draggable({ 
					cancel: false,
					revert: function(event, ui) {
						// jQuery 1.x Version:
						// $(this).data("draggable")
						// jQuery 2.x Version:
						// $(this).data("ui-draggable")
						$(this).data("ui-draggable").originalPosition = {
						    top : 0,
						    left : 0
						};
						// return boolean
						return !event;
						// Kurzform für: return event !== false ? false : true;
					}
				});
				$(".draggable").css('position','relative');

			}else{
				// Standardausgabe der Tabellen mit Fade Effekt und eingeklappten Tabellen
				$($target).html('').append($echoData).fadeOut(0).ready(hide_all_tr('#'+$tbl,0)).fadeIn(500);
			}
		});
	}
}

function positionDevices($chosenRoom){
// Wenn die Tabellen geladen sind, sollen alle Geräte im Raum an die entsprechende Position geschoben werden.
	// Feststellen welche Geräte im Raum sind!
	$.post("getSelRoomDevices.php", {chosenRoom : $chosenRoom},
		function($echoData){

		// Alle Geräte in $echoData in Position bringen!
			// Debugging
			console.log(".....................");
			console.log(".Laden...............");
			console.log("chosenRoom: " + $chosenRoom);
			console.log($echoData);

			// Tabelle versteckt ausgeben
			$("#hiddenTable").hide().html($echoData);

			// Wie viele Geräte sind in der Tabelle?
			var $anzDevice = $("div#hiddenTable table > tbody > tr").length;

			//Zeile für Zeile auswerten
			for($zeile = 1; $zeile <= $anzDevice; $zeile++){
				// ID & Position auslesen
				$ID = $("div#hiddenTable table > tbody > tr:nth-child(" + $zeile + ") > td:nth-child(1)").html();
				$X  = $("div#hiddenTable table > tbody > tr:nth-child(" + $zeile + ") > td:nth-child(2)").html();
				$Y  = $("div#hiddenTable table > tbody > tr:nth-child(" + $zeile + ") > td:nth-child(3)").html();

				// Debugging
				console.log("ID: " + $ID);
				console.log("X: " + $X);
				console.log("Y: " + $Y);
				console.log("Moved Button ID: button#" + $ID);

				// Grundrissgröße bestimmen
				var $groundplotWidth = $("div#SelectedRoom").width();
				var $groundplotHeight = $("div#SelectedRoom").height();
				$groundplotHeight = $groundplotHeight * (-1);

				// Debugging
				console.log("Grundrissbreite: " + $groundplotWidth + "px");
				console.log("Grundrisshöhe: " + $groundplotHeight + "px");

				// Berechnen der Position in px vom Bildrand
				var $posInsidePicX = ($groundplotWidth / 1000) * $X;
				var $posInsidePicY = ($groundplotHeight / 1000) * $Y * (-1);

				// Debugging
				console.log("Position X des Gerätes im Bild: " + $posInsidePicX + "px");
				console.log("Position Y des Gerätes im Bild: " + $posInsidePicY + "px");

				// Berechnen des Offset des Grundrissbildes:
				var $offsetOfPicX = $("div#SelectedRoom").offset().left;
				var $offsetOfPicY = $("div#SelectedRoom").offset().top;
				$offsetOfPicY = $offsetOfPicY * (-1);

				// Debugging
				console.log("Offset X des Bildes: " + $offsetOfPicX + "px");
				console.log("Offset Y des Bildes: " + $offsetOfPicY + "px");

				// Position im Bild auf Offset des Bildes drauf rechnen um absolute Position zu erhalten
				var $absX = $posInsidePicX + $offsetOfPicX;
				var $absY = $posInsidePicY + $offsetOfPicY;
				$absY = $absY * (-1);

				// Debugging
				console.log("Absolute Position X: " + $absX + "px");
				console.log("Absolute Position Y: " + $absY + "px");

				// Positionieren des Device in die Absolute Position
				$("button#" + $ID).offset({top: $absY, left: $absX});

				// Debugging
				console.log(".....................");
			}

			// Debugging
			console.log("Anzahl enthaltener Geräte: " + $anzDevice);
			console.log(".....................");
		});
}

1 个答案:

答案 0 :(得分:1)

您的代码有几个问题:

首先,正如我在评论中所解释的那样$.when()没有神奇的力量,它只能在异步操作完成时通知你,如果你传递一个或多个承诺。您将getSelectedRoom()的返回结果传递给undefined,因此$.when()未传递承诺,因此只是立即调用它的.done()处理程序。而且,一旦您从getSelectedRoom()返回承诺,您根本不需要使用$.when()因为您只有一个承诺,您可以直接使用.then()$.when()仅在您有多个承诺时通知异步完成时才有用,并且您想知道它们何时完成。

只需更改此内容即可轻松解决此问题:

function getSelectedRoom($chosenRoom){
// Ausgewählten Raum mit platzierten Geräten anzeigen
    // Raumgrundriss laden
    $.post("getSelectedRoom.php", {chosenRoom : $chosenRoom},
    ....
}

到此:

function getSelectedRoom($chosenRoom){
// Ausgewählten Raum mit platzierten Geräten anzeigen
    // Raumgrundriss laden
    return $.post("getSelectedRoom.php", {chosenRoom : $chosenRoom},
    ....
}

现在,您从$.post()返回getSelectedRoom()的jQuery ajax承诺,现在可以执行此操作:

getSelectedRoom(...).then(function() {
    getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom);

});

其次,如果您正在尝试测量刚刚插入的某些HTML的大小,那可能会也可能不会起作用,因为浏览器可能已经或可能没有完成布局/重绘(重绘是否已经发生将取决于关于promise库的一些实现细节)。你可以通过这样做保证重绘:

getSelectedRoom(...).then(function() {
    setTimeout(function() {
        getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom);
    }, 1);
});