在第一个功能完成后,启动第二个功能。
Start a second function, after the first one has been completed.
我对 jQuery 和 AJAX 有疑问。
我有 2 个函数,做一些 AJAX - 东西:
1:
getSelectedRoom($chosenRoom)
和
2:
getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom)
第一个函数创建 div 并插入图像。现在,完成后,我需要 div 的高度以及里面的图像。因此我需要第二个函数等待,直到第一个函数完成所有操作。
我认为下面的代码可以解决我的问题,但是第二个函数有时会在 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(".....................");
});
}
您的代码有几个问题:
首先,正如我在评论中解释的那样,$.when()
没有神奇的力量,如果您向它传递一个或多个承诺,它只能在异步操作完成时通知您。您将 getSelectedRoom()
的 return 结果传递给它,即 undefined
所以 $.when()
没有传递承诺,因此只是调用它的 .done()
处理程序立即地。而且,一旦你 return 得到 getSelectedRoom()
的承诺,你根本不需要使用 $.when()
因为你只有一个承诺,你可以只使用 .then()
直接上。 $.when()
仅在您有多个 promise 并且您想知道它们何时全部完成时才用于通知异步完成。
只需更改以下内容即可轻松解决此问题:
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},
....
}
现在,您正在 returnjQuery ajax $.post()
和 getSelectedRoom()
的承诺,所以现在可以这样做了:
getSelectedRoom(...).then(function() {
getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom);
});
其次,如果您尝试测量刚刚插入的某些 HTML 的大小,这可能会或可能不会工作,因为浏览器可能还没有完成 layout/repaint (重绘是否发生将取决于 promise 库的一些实现细节)。您可以通过这样做来保证重绘已经发生:
getSelectedRoom(...).then(function() {
setTimeout(function() {
getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom);
}, 1);
});
我对 jQuery 和 AJAX 有疑问。
我有 2 个函数,做一些 AJAX - 东西:
1:
getSelectedRoom($chosenRoom)
和
2:
getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom)
第一个函数创建 div 并插入图像。现在,完成后,我需要 div 的高度以及里面的图像。因此我需要第二个函数等待,直到第一个函数完成所有操作。
我认为下面的代码可以解决我的问题,但是第二个函数有时会在 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(".....................");
});
}
您的代码有几个问题:
首先,正如我在评论中解释的那样,$.when()
没有神奇的力量,如果您向它传递一个或多个承诺,它只能在异步操作完成时通知您。您将 getSelectedRoom()
的 return 结果传递给它,即 undefined
所以 $.when()
没有传递承诺,因此只是调用它的 .done()
处理程序立即地。而且,一旦你 return 得到 getSelectedRoom()
的承诺,你根本不需要使用 $.when()
因为你只有一个承诺,你可以只使用 .then()
直接上。 $.when()
仅在您有多个 promise 并且您想知道它们何时全部完成时才用于通知异步完成。
只需更改以下内容即可轻松解决此问题:
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},
....
}
现在,您正在 returnjQuery ajax $.post()
和 getSelectedRoom()
的承诺,所以现在可以这样做了:
getSelectedRoom(...).then(function() {
getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom);
});
其次,如果您尝试测量刚刚插入的某些 HTML 的大小,这可能会或可能不会工作,因为浏览器可能还没有完成 layout/repaint (重绘是否发生将取决于 promise 库的一些实现细节)。您可以通过这样做来保证重绘已经发生:
getSelectedRoom(...).then(function() {
setTimeout(function() {
getDeviceTable("all", "div#DeviceTables",0,1,1,0,1,$chosenRoom);
}, 1);
});