0

I'm trying to make a registration page that tells the user whether the username they have selected is unique without reloading the page. The php script 'usernameAJAX.php' simply queries the sql database and returns a "1" if the username is not unique and a "0" if it is. For some reason, nothing is returned from the usernameAJAX(username) function i've created, not even the 'bool' variable set to "0" on the third line. Can someone explain why this is happening?

function usernameAJAX(username) {

var bool = "0";

params  = "AJAXusername=" + username.value;
  request = new ajaxRequest();
  request.open("POST", "usernameAJAX.php", true);
  request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  request.setRequestHeader("Content-length", params.length);
  request.setRequestHeader("Connection", "close");

  request.onreadystatechange = function()
  {
    if (this.readyState == 4)
      if (this.status == 200)
        if (this.responseText != null)
          bool = this.responseText;
  }
  request.send(params);


function ajaxRequest()
{
  try { var request = new XMLHttpRequest(); }
  catch(e1) {
    try { request = new ActiveXObject("Msxml2.XMLHTTP"); }
    catch(e2) {
      try { request = new ActiveXObject("Microsoft.XMLHTTP"); }
      catch(e3) {
        request = false;
  } } }
  return request;
}

return bool;

}

iCode101
  • 395
  • 2
  • 17

3 Answers3

1

Your function is correct, but you must remove the headers Content-length and Connection. In addition, you must notice that your function will always return 0. If you want to do something with the downloaded value, you must do it here:

function usernameAJAX(username, callback) {
    ...
    if (this.responseText != null) {
        bool = this.responseText;
        callback(bool);
    }
    ...
}


var show = function (bool) {
    alert(bool);
};

// The execution continues in the callback function when bool is downloaded.
usernameAJAX("usuario", show);

If you want return the bool value in a traditional way, you must use a non asynchronous petition, in this way the window will be blocked while the value is being downloaded and you will waste the advantage of AJAX.

Wandeber
  • 376
  • 3
  • 10
  • Why must the headers be removed? Is there no way of returning the downloaded value into the usernameAJAX(username) function instead? – iCode101 Aug 11 '14 at 23:58
  • yes but you must format the response, you cannot just use it raw like that, which is why AJAX is always wrapped in a format like JSON or XML – Wobbles Aug 11 '14 at 23:59
  • Webkit browsers consider that these headers are unsafe. – Wandeber Aug 12 '14 at 00:05
  • And... a way of returning the dowloaded value... Usually you want use that value when it is downloaded (obviously... yeah). You can use a callback function that executes when the value is downloaded. Something like... callback(bool); I will edit my answer, just a second. – Wandeber Aug 12 '14 at 00:09
0

AJAX calls almost always return hidden or special/terminator characters, Use trim commands to format the response before using it or better yet wrap the return in JSON or XML.

Wobbles
  • 3,033
  • 1
  • 25
  • 51
  • The return is a normal string. If I change the script so that instead of `bool = this.responseText` it reads `document.getElementFromId('some_element').innerHTML= this.responseText`, the element displays the correct text. I just can't get it to store the return in the bool variable ?! – iCode101 Aug 11 '14 at 23:55
  • use `bool = boolean(this.responseText);` but its probably always going to return true since as I said there are special characters in AJAX responses. – Wobbles Aug 11 '14 at 23:58
0

As it is, usernameAJAX() always returns before the request is completed. So its return value will always be '0'.

UPDATE: Forgot to put the actual fix.

Make the request non-asynchronous by changing

request.open("POST", "usernameAJAX.php", true);

to

request.open("POST", "usernameAJAX.php", false);

if you want usernameAJAX() to return the result itself, and not through a callback.

This way, request.send(params); will be blocking the execution within usernameAJAX() until the connection is closed or ends up in an error. During this time, request.onreadystatechange will have been called every time request.readyState changes.

The downside is that UI might become unresponsive during that short amount of time while the XMLHttpRequest object waits for the answer (or ends up timing out).

johnwait
  • 1,135
  • 7
  • 17
  • How would I rewrite the function so that `return bool` is executed after the ajax request is completed (i.e. when `bool=this.responseText`)? – iCode101 Aug 12 '14 at 00:17
  • the function is hooked to the `onreadystatechange` event and is filtered by both state and status, OP's code is correct for a async AJAX call. – Wobbles Aug 12 '14 at 00:32
  • But if I were you I would use an asynchronous call with a callback, like @B3rAS showed. You would then write the callback so it acts upon the result of the AJAX request (e.g. show a message that says username has already been taken) – johnwait Aug 12 '14 at 00:33
  • callback isn't really necessary, somthing as simple as this could be handled inside the event function, just need to add the actual validation code inside `if (this.responseText != null)`... which this line isnt even necessary since we are already testing for response 200 – Wobbles Aug 12 '14 at 00:36
  • 1
    @Wobbles: Sorry to argue, but you're wrong. The anonymous function is assigned to `request.onreadystatechange`, not executed. If the request is asynchronous `request.send(params);` will return immediately, most probably before `request.readyState` has even reached `READYSTATE_COMPLETE` (4), and thus `usernameAJAX()` will return `bool` unchanged. – johnwait Aug 12 '14 at 00:40
  • @johnwait sorry to argue back, but even async AJAX calls raise the readystatechange event, been using it for years, this is why you have to use the state=4 and 200 response checks because this function is actually raised several times throughout the AJAX cycle, hes just not doing anything with it here, its just setting an already returned bool instead of creating a dynamic message like im sure he intends. – Wobbles Aug 12 '14 at 00:50