首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Ajax 異步驗證表單導致需點擊兩次提交:同步回調陷阱與正確異步處理模式

     編輯:程式設計綜合問答

問題代碼邏輯


function formsubmit() {
    xmlhttp.open("post", url, true); // 異步
    xmlhttp.onreadystatechange = function() {
        if (readyState==4 && status==200) {
            span.innerHTML = responseText; // 異步回調賦值
        }
    };
    xmlhttp.send(null);
    // 這裡立即執行,異步請求尚未完成,span 仍為初始值 ""
    if (span.innerHTML == "") return true;  // 直接返回 true 提交
    else return false;
}

根本原因

**異步請求非阻塞**:`send()` 後代碼立即繼續執行,`onreadystatechange` 回調在未來某時觸發。判斷 `span.innerHTML` 時請求尚未返回,永遠為初始值,導致首次點擊直接提交 (驗證未生效),二次點擊時回調已完成,驗證生效阻止提交。

正確模式:回調內決定提交


function formsubmit() {
    var xmlhttp = ajaxfun();
    var data = document.getElementById("data").value;
    var url = "datacheckaction?data=" + encodeURIComponent(data) + "&time=" + Date.now();
    
    xmlhttp.open("post", url, true);
    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var result = xmlhttp.responseText;
            document.getElementById("spandata").innerHTML = result;
            if (result == "") {
                // 驗證通過,手動提交表單
                document.forms[0].submit(); // 或 document.getElementById("myForm").submit()
            } else {
                // 驗證失敗,提示用戶,不提交
                alert("驗證失敗: " + result);
            }
        }
    };
    xmlhttp.send(null);
    return false; // **始終阻止默認提交**,由回調控制
}

現代替代:Fetch + Async/Await (更清晰)


async function formsubmit() {
    const data = document.getElementById("data").value;
    const url = `datacheckaction?data=${encodeURIComponent(data)}&time=${Date.now()}`;
    try {
        const resp = await fetch(url, {method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}});
        const result = await resp.text();
        document.getElementById("spandata").innerHTML = result;
        if (result === "") {
            document.getElementById("myForm").submit();
        } else {
            alert("驗證失敗: " + result);
        }
    } catch (e) {
        console.error(e); alert("網絡異常");
    }
    return false;
}
// HTML: 

關鍵原則

  1. `onsubmit` 返回 `false` 阻止默認提交。
  2. 異步驗證**成功回調中**調用 `form.submit()` 手動提交。
  3. 失敗回調中**不提交**,僅提示。
  4. 使用 `fetch`/`axios` 替代原生 `XMLHttpRequest`,代碼更線性、錯誤處理更完善。

異步編程核心:**不要試圖將異步結果同步化**,順應回調/Promise 流程控制提交時機。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved