问题
I have a function that I wish to dynamically generate an HTML table using data that it grabs from an SQL call. As you can see the function receives a groupID and passes it to a function populateDB, which when called will perform an AJAX call to retrieve some data from a DB. I need that data from that AJAX call immediately after the AJAX call before the next lines of code are executed. I know that AJAX is asynchronous and that the rest of the code will execute probably before the data is returned from the AJAX call. I also know that the use of callback functions often help in these situations. I have read this stack post over and over: How do I return the response from an asynchronous call?
However, in this instance, and after hours of problem solving, I cannot see how I can program a callback to work for me here. I am sure I am just not clever enough but I would be so grateful for someone to lend me a hand and show me how I can call the populateDB function and wait for a response, then get that response back into the makeEditTableHTML function for further processing.
function makeEditTableHTML(studentArray, groupID) {
populateDB(groupID);
--- I NEED THE DATA/ARRAY FROM THE AJAX CALL HERE ---
var result = "<table id='dataEditTableid' class='stripe' border=1><thead><tr><td><b>ID</b></td><td><b>Student Email</b></td><td><b>Group ID</b></td><td><b>Target</b></td><td><b>SEN</b></td><td><b>Disadvantaged</b></td></tr></thead>";
result += "<tbody>";
for(var i=0; i<studentArray.length; i++) {
result += "<tr>";
result += "<td>"+studentArray[i][1]+"</td>";
result += "<td>"+studentArray[i][0]+"</td>";
result += "<td>"+groupID+"</td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(1, this.id, this.innerHTML, "+groupID+")'></td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(2, this.id, this.innerHTML, "+groupID+")'></td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(3, this.id, this.innerHTML, "+groupID+")'></td>";
result += "</tr>";
}
result += "</tbody></table>";
return result;
}
AJAX call function:
function populateDB(groupID) {
$(document).ready(function(){
$.ajax({
type: "POST",
url: {$js_url} + '/wp-content/plugins/WickCustomLD/sqlPopulateDB.php',
data: {"groupID" : groupID},
success: function(data) {
data = JSON.parse(data);
},
})});
}
Original makeEditTableHTML function call code:
var result_table = makeEditTableHTML(MultiStudList[groupIndex], groupIDs[groupIndex]);
dataTable.innerHTML = result_table;
回答1:
Refactor your code as follows, pass in a success callback to $.ajax.
function populateDB(groupID, successCb) {
$(document).ready(function(){
$.ajax({
type: "POST",
url: {$js_url} + '/wp-content/plugins/WickCustomLD/sqlPopulateDB.php',
data: {"groupID" : groupID},
success: successCb
});
});
}
function makeEditTableHTML(groupID, studentArray, successCb) {
return populateDB(groupID, function(data) {
// Data from AJAX POST
console.log(data);
var result = "<table id='dataEditTableid' class='stripe' border=1><thead><tr><td><b>ID</b></td><td><b>Student Email</b></td><td><b>Group ID</b></td><td><b>Target</b></td><td><b>SEN</b></td><td><b>Disadvantaged</b></td></tr></thead>";
result += "<tbody>";
for(var i=0; i < studentArray.length; i++) {
result += "<tr>";
result += "<td>"+studentArray[i][1]+"</td>";
result += "<td>"+studentArray[i][0]+"</td>";
result += "<td>"+groupID+"</td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(1, this.id, this.innerHTML, "+groupID+")'></td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(2, this.id, this.innerHTML, "+groupID+")'></td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(3, this.id, this.innerHTML, "+groupID+")'></td>";
result += "</tr>";
}
result += "</tbody></table>";
return successCb(result);
});
}
// In the calling function
makeEditTableHTML(MultiStudList[groupIndex], groupIDs[groupIndex], function(result_table) {
dataTable.innerHTML = result_table;
});
回答2:
If you like to experiment, try below suggestion too, first make the Ajax call and in the success callback, construct the table. And remove document.ready() while making Ajax call as it is not required.
Instead of calling makeEditTableHTML, call populateDB method on dropdown item changed.
function populateDB(studentArray, groupID) {
$.ajax({
type: "POST",
url: {
$js_url + '/wp-content/plugins/WickCustomLD/sqlPopulateDB.php',
}
data: {
"groupID": groupID
},
success: function(data) {
makeEditTableHTML(groupID, studentArray, data);
},
});
}
function makeEditTableHTML(groupID, studentArray, data = []) { // Provide default value to **data** parameter
console.log(data);
var result = "<table id='dataEditTableid' class='stripe' border=1><thead><tr><td><b>ID</b></td><td><b>Student Email</b></td><td><b>Group ID</b></td><td><b>Target</b></td><td><b>SEN</b></td><td><b>Disadvantaged</b></td></tr></thead>";
result += "<tbody>";
for (var i = 0; i < studentArray.length; i++) {
result += "<tr>";
result += "<td>" + studentArray[i][1] + "</td>";
result += "<td>" + studentArray[i][0] + "</td>";
result += "<td>" + groupID + "</td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(1, this.id, this.innerHTML, " + groupID + ")'></td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(2, this.id, this.innerHTML, " + groupID + ")'></td>";
result += "<td id=" + studentArray[i][1] + " contenteditable='true' onBlur='saveToDB(3, this.id, this.innerHTML, " + groupID + ")'></td>";
result += "</tr>";
}
result += "</tbody></table>";
dataTable.innerHTML = result_table;
}
回答3:
We can't simply return if we are working with async requests, instead of return we should append data in HTTML DOM.
In your case, you are getting undefined because when you try to generate table, data was not there or i should say AJAX call not completed yet. And when AJAX call completed, DOM has completed its working. now we have to update the DOM like i have done using innerHTML
function loadUserData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
renderTable(JSON.parse(this.responseText));
}
};
xhttp.open("GET", "https://jsonplaceholder.typicode.com/users", true);
xhttp.send();
}
function renderTable(studentArray){
var result = "<table border=1><thead><tr><td><b>ID</b></td><td><b>Email</b></td><td><b>Username</b></td><td><b>Name</b></td><td><b>City</b></td></tr></thead>";
result += "<tbody>";
for (var i = 0; i < studentArray.length; i++) {
result += "<tr>";
result += "<td>" + studentArray[i]['id'] + "</td>";
result += "<td>" + studentArray[i]['email'] + "</td>";
result += "<td>" + studentArray[i]['username'] + "</td>";
result += "<td>" + studentArray[i]['name'] + "</td>";
result += "<td>" + studentArray[i]['address']['city'] + "</td>";
result += "</tr>";
}
result += "</tbody></table>";
document.getElementById("demo").innerHTML = result
}
<!DOCTYPE html>
<html>
<body>
<h2>Generate Table for User Data</h2>
<button type="button" onclick="loadUserData()">Load User Data</button>
<p id="demo"></p>
</body>
</html>
来源:https://stackoverflow.com/questions/62951747/how-to-receive-data-from-ajax-call-inside-the-same-function