使用 Ajax 调用从函数返回值

IT技术 javascript ajax asynchronous
2021-01-25 12:36:01

有人能告诉我如何将 的值status作为函数的返回值返回。

function checkUser() {
    var request;
    var status = false;

    //create xmlhttprequest object here [called request]

    var stu_id = document.getElementById("stu_id").value;
    var dName = document.getElementById("dName").value;
    var fileName = "check_user.php?dName=" + dName + "&stu_id=" + stu_id;
    request.open("GET", fileName, true);
    request.send(null);

    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            var resp = parseInt(request.responseText, 10);
            if(resp === 1) {
                alert("The display name has already been taken.");
                status = false;
            }
            else if(resp === 2) {
                alert("This student ID has already been registered");
                status = false;
            }
            else if(resp === 0) {
                status = true;
            }
        }
    }
    return status;
}

当您在注册表单中点击提交时会触发上述功能(必须很明显)。问题是,无论响应是什么,此表单都会提交,并且警告框有时不显示任何内容 [空白],有时根本不显示。但是,如果我将结尾更改statusfalse手动 [即替换statusfalse],警报框中会显示正确的值。

PS我比javascript中的菜鸟更糟糕,所以也欢迎关于总体改进代码的建议。

2个回答

问题是它onreadystatechange不会触发直到......等待它......状态改变。所以当你return status;大部分时间状态不会来得及设置。您需要做的是return false;始终在内部onreadystatechange确定是否要继续。如果你这样做,那么你提交表格。简而言之,使用处理返回值的代码,而是从 readystatechange 处理程序中运行它。您可以直接执行此操作:

request.onreadystatechange = function() {
    if (request.readyState == 4) {
        var resp = parseInt(request.responseText, 10);
        switch (resp) {
        case 0:
            document.getElementById('myform').submit();
            break;
        case 1:
            alert("The display name has already been taken.");
            break;
        case 2:
            alert("This student ID has already been registered");
            break;
        }
    }
}
return false; // always return false initially

或者通过将延续传递给进行异步调用的函数:

function checkUser(success, fail) {
    ...
    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            var resp = parseInt(request.responseText, 10);
            switch (resp) {
            case 0:
                success(request.responseText);
            case 1:
                fail("The display name has already been taken.", request.reponseText);
                break;
            case 2:
                fail("This student ID has already been registered", request.reponseText);
                break;
            default:
                fail("Unrecognized resonse: "+resp, request.reponseText);
                break;
            }
        }
    }

除此之外,在默认之前,return false;您可能想要某种指示正在发生的事情,也许禁用提交字段,显示加载圆圈等。否则如果需要很长时间来获取用户可能会感到困惑数据。

进一步说明

好的,所以你的方式不起作用的原因主要是在这一行:

request.onreadystatechange = function() {

这样做是说当onreadystatechangeAJAX 请求的 更改时,您定义的匿名函数将运行。此代码不会立即执行。它正在等待事件发生。这是一个异步过程,所以在函数定义的最后,javascript 将继续运行,如果状态在它到达return status;变量时没有改变,status显然没有时间设置并且您的脚本将无法按预期工作. 这种情况下的解决方案是始终return false;,然后当事件触发时(即,服务器响应 PHP 的脚本输出),然后您可以确定状态并在一切正常时提交表单。

非常感谢您的快速回复。您的解决方案完美无缺。但是,我不明白为什么从条件内部设置状态值不起作用。对此的一些提示将不胜感激。
2021-03-20 12:36:01
非常感谢。是的,这有帮助。
2021-03-22 12:36:01
我编辑了我的答案,更详细地解释了正在发生的事情。如果有帮助,请告诉我。干杯。
2021-04-13 12:36:01

这是可能同步执行的发送方法,所以request.responseText会立即可用,但它不是通常一个好主意。该请求将挂起浏览器,直到它完成。

要将请求设置为同步,请将 request.open 的第三个参数设置为“false”。

function checkUser() {
    var request;
    var status = false;

    //create xmlhttprequest object here [called request]

    var stu_id = document.getElementById("stu_id").value;
    var dName = document.getElementById("dName").value;
    var fileName = "check_user.php?dName=" + dName + "&stu_id=" + stu_id;
    request.open("GET", fileName, false);
    request.send(null);

    if (request.status === 200) {
        var resp = parseInt(request.responseText, 10);
        if(resp === 1) {
            alert("The display name has already been taken.");
            status = false;
        }
        else if(resp === 2) {
            alert("This student ID has already been registered");
            status = false;
        }
        else if(resp === 0) {
            status = true;
        }
    }
    else {
        alert("Request failed");
        status = false;
    }

    return status;
}

正如我之前提到的,这不是一个好主意异步执行请求几乎总是一个更好的主意,这样其他代码就可以在您等待响应时运行。A jax 流行而不是S jax是有原因

一篇文章简要解释了为什么在同步模式下使用 XMLHttpRequest 不是一个好主意 - developer.mozilla.org/En/...
2021-03-18 12:36:01