Retorna o valor da function com uma chamada Ajax

Alguém pode me dizer como retornar o valor do status como valor de retorno da function.

 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; } 

A function acima é acionada quando você clica em enviar em um formulário de registro (como deve ser óbvio). O problema é que esse formulário é enviado independentemente da resposta, e a checkbox de alerta às vezes não mostra nada [em branco], às vezes não é exibida. No entanto, se eu alterar o status final para false manualmente [ou seja, replace status por false ], o valor correto será exibido na checkbox de alerta.

PS Eu sou pior do que um noob em javascript, então sugestões sobre como melhorar o código também são bem-vindas.

O problema é que onreadystatechange não será triggersdo até … aguardar … o estado muda. Então, quando você return status; a maior parte do tempo não terá tempo para definir. O que você precisa fazer é return false; sempre e dentro do onreadystatechange determinar se você deseja prosseguir ou não. Se você fizer isso, envie o formulário. Em suma, pegue o código que manipula o valor de retorno e, em vez disso, execute-o a partir do manipulador readystatechange. Você pode fazer isso diretamente:

 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 

ou passando uma continuação para a function que faz a chamada assíncrona:

 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; } } } 

Além disso, antes do return false; padrão, return false; talvez você queira ter algum tipo de indicador de que algo está acontecendo, talvez desative o campo de envio, mostre um círculo de carregamento etc. Caso contrário, os usuários poderão ficar confusos se demorar muito para buscar os dados.

Mais explicações

Tudo bem, então a razão pela qual o seu caminho não funcionou é principalmente nesta linha:

 request.onreadystatechange = function() { 

O que isso está fazendo é dizer que quando o onreadystatechange do pedido AJAX muda, a function anônima que você está definindo será executada. Este código não está sendo executado imediatamente. Está esperando por um evento acontecer. Este é um processo asynchronous, portanto, no final da definição da function, o javascript continuará, e se o estado não foi alterado no momento em que ele return status; o status da variável obviamente não terá tempo para definir e seu script não funcionará como esperado. A solução neste caso é sempre return false; e quando o evento é acionado (isto é, o servidor respondeu com a saída do script do PHP), você pode determinar o status e enviar o formulário se tudo estiver ok.

É possível executar o método de envio de forma síncrona, então request.responseText estará disponível imediatamente, mas normalmente não é uma boa idéia. A solicitação interromperá o navegador até que seja concluído.

Para definir a solicitação como síncrona, defina o terceiro parâmetro como request.open como “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; } 

Como eu mencionei antes, porém, isso não é uma boa ideia . É quase sempre uma ideia melhor fazer a solicitação de forma assíncrona, para que outro código possa ser executado enquanto você aguarda uma resposta. Há uma razão que um jax pegou em vez de S jax.