Возвращаемое значение из функции с вызовом Ajax

Может кто-нибудь сказать мне, как вернуть значение 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;
}

Вышеуказанная функция срабатывает, когда вы нажимаете кнопку отправить в регистрационной форме (как должно быть очевидно). Проблема в том, что эта форма отправляется независимо от ответа, а в окне предупреждения иногда ничего не отображается [пусто], а иногда вообще не отображается. Однако, если я изменю окончание status в false вручную [т.е. заменить status с false], правильное значение отображается в окне предупреждения.

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() {

То, что это делает, говорит, что когда onreadystatechange изменений AJAX-запроса будет выполняться заданная вами анонимная функция. Этот код НЕ выполняется сразу. Он ждет события, которое произойдет. Это асинхронный процесс, поэтому в конце определения функции javascript будет продолжать работать, и если состояние не изменилось к тому времени, как return status; переменная status очевидно, не было времени для установки, и ваш сценарий не будет работать, как ожидалось. Решение в этом случае всегда return false; и затем, когда происходит событие (т. е. сервер ответил выводом скрипта PHP), вы можете определить статус и отправить форму, если все в порядке.

Возможно выполнить метод send синхронно, поэтому 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;
}

Как я уже упоминал ранее, это не очень хорошая идея. Почти всегда лучше выполнять запрос асинхронно, чтобы другой код мог выполняться, пока вы ожидаете ответа. Есть причина, по которой прижился Jax вместо S Jax.

Другие вопросы по тегам