當我正在學習/編碼時,又帶著蹩腳的問題來到這里。
我想更改按鈕上禁用值的屬性:在執行其作業的函式期間,應禁用按鈕,一旦函式完成并回傳值,應再次啟用按鈕。
在創建按鈕的函式中,我呼叫 update() 函式,該函式通過 XMLHttpRequest 加載 php 檔案。然后運行 ??php 代碼并在頁面上回傳值。我想在這段時間內禁用按鈕。但是每次我呼叫該功能時,按鈕都不會改變。或者如果改變它是如此之快,我什至沒有看到它。
這是一個代碼:
global_button = document.createElement("button");
// let btn1 = document.createElement("button");
global_button.innerHTML = "UPDATE";
global_button.id = "update";
global_button.disabled = false;
document.body.appendChild(global_button);
document.getElementsByClassName("two")[0].append(global_button);
global_button.addEventListener("click", function () {
console.log("After CLICKED");
global_button.disabled = true;
update();
global_button.disabled = false;
console.log("AFTER FUNCTION RETURN VALUES");
更新功能:
var xmlhttp;
function loadFile(file, func){
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = func;
xmlhttp.open("GET", file, true);
xmlhttp.send();
}
function update(){
loadFile("update.php", function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("content").innerHTML = xmlhttp.responseText;
}
});
}
當我檢查控制臺時,它會立即顯示兩個控制臺日志:“點擊后”和“后功能回傳值”訊息。幾秒鐘后,函式的結果出現了。但是按鈕不會改變。
我懷疑同步/異步功能?我為 .open 方法和 vale true/false 閱讀了一些內容,但如果我從 true 切換到 false,則沒有任何變化。還想我是否應該把它放在回圈上或者檢查按鈕點擊的東西?但我認為聽眾會做這項作業。
有人可以檢查并給我建議嗎?或者糾正我的想法,如果它是錯誤的?
非常感謝你們。:)
uj5u.com熱心網友回復:
問題確實是由于-send方法的異步性質,因此呼叫它XMLHttpRequest的你的方法。update
當你打電話時update(),它本身稱之為:
loadFile("update.php", function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("content").innerHTML = xmlhttp.responseText;
}
});
所發生的只是你設定了一個XMLHttpRequest物件并使用它的send方法發送一個請求,告訴它呼叫這個函式:
function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("content").innerHTML = xmlhttp.responseText;
}
});
作為readyState更改時的“回呼”。(特別是當請求完成并收到回應時。)但呼叫update不會等待狀態更改發生并阻止您的代碼運行 - 因此下一行代碼disabled將按鈕的狀態設定為 false并登錄到控制臺 - 立即執行。因此該按鈕被禁用但隨后立即取消禁用,因此您永遠不會看到它被禁用。(事實上??,瀏覽器甚至永遠不會使用禁用按鈕“繪制”螢屏,因為在您的代碼運行時它沒有機會這樣做,所以即使您理論上可以在這里做一個定格,您也會永遠不會看到禁用的按鈕。)
要修復它,您必須使用正在使用的異步代碼。狀態改變后你想要發生的任何事情都必須在你傳遞給它的回呼函式中發生。update因此,您可以通過將定義更改為以下內容來簡單地解決您的問題:
function update(){
loadFile("update.php", function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("content").innerHTML = xmlhttp.responseText;
global_button.disabled = false;
console.log("AFTER FUNCTION RETURN VALUES");
}
});
}
update并在通話后從您當前擁有它們的地方洗掉這兩行代碼。
盡管請注意,這僅global_button在位于 inside 范圍內時才有效update,這可能不取決于您的代碼的結構方式(老實說,這可能不應該)。即使是這樣,硬編碼update之后總是禁用按鈕也不好,不能保證按鈕甚至會首先被禁用。
因此,最好為update自己定義一個回呼函式:
function update(callback){
loadFile("update.php", function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("content").innerHTML = xmlhttp.responseText;
callback();
}
});
}
然后在你的主代碼中這樣呼叫它:
global_button.disabled = true;
update(function() {
global_button.disabled = false;
console.log("AFTER FUNCTION RETURN VALUES");
});
因為這將其update自身的關注點(“發出此請求并將content內部 HTML 設定為回應”)與您之后可能想要做的任何事情分開,每次都可能不同。
最后不得不提的是,這種基于回呼的異步代碼現在已經很老套了。XMLHTTPRequest本身就是一個相當繁瑣的 API。我強烈建議您研究它的現代等價物,fetch它基于 Promises - 雖然并非沒有他們的心理陷阱,但它是一種更容易理解的撰寫異步代碼的方式。特別是async,await您可以撰寫看起來很像您最初擁有的代碼:putawait update();實際上會執行您正在等待的操作,并讓您的其余代碼等待update完成。但是您不能只對原始代碼進行更改,因為只有在update回傳 Promise 時才有效,這反過來意味著完全重寫您loadFile以使用更現代的、基于 Promise 的方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/532009.html
