我遇到了jQuery& amp; AJAXs。
我有2个函数,做一些AJAX - Stuff:
getSelectedRoom($chosenRoom)
和
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(".....................");
});
}
答案 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);
});