Hi,

> If the function "show_message" is in " new Ajax.Request()" , the result
> corresponds to the Request.
> But if  the function "show_message" is outside "new Ajax.Request()" then the
> result corresponds to the previous Request.
> I don't understand why ?

It's because Ajax requests are *asynchronous* (by default). Let's take
an example of a request that returns a plain text response which will
be "SUCCESS:data" on success, or "ERROR" on error:

function foo(url) {
    var data;

    new Ajax.Request(url, {
        onSuccess: function(response) {
            if (response.responseText.substring(0, 8) === "SUCCESS:")
{
                data = response.responseText.substring(8);
            }
            else {
                data = "(could not get data)";
            }
        }
    });

    alert(data); // <== WRONG, always alerts 'undefined'
}

What happens when we call `foo` in the above is:

1. A new request is created and started.
2. `alert` is called, showing the current value of `data` which is, of
course, `undefined` because nothing has ever been assigned to it.
3. `foo` returns.
4. At some point in the future, the request completes and sets the
`data` variable. Nothing ever does anything with it, though.

Compare with:

function foo(url) {
    var result;

    new Ajax.Request(url, {
        onSuccess: function(response) {
            if (response.responseText.substring(0, 8) === "SUCCESS:")
{
                data = response.responseText.substring(8);
            }
            else {
                data = "(could not get data)";
            }
            alert(data);
        }
    });
}

Now here's what happens when we call `foo`:

1. A new request is created and started.
2. `foo` returns.
3. At some point in the future, the request completes and sets the
`data` variable.
4. `alert` is called, showing the current value of `data` (which is
what we just assigned to it).

So what do you do about it? Put your processing of the result in the
success callback (as above), rather than in the code that's starting
the Ajax request. Sometimes this means that you have to provide
callbacks to code calling your function. For instance, let's assume
that `foo` is supposed to *return* `data` to the caller rather than
using `alert`. We now know that `foo` can't do that with a return
value -- because `foo` returns before the Ajax call is complete. So
how would `foo` pass the information back to the caller? Via a
callback:

function foo(url, callback) {
    var data;

    new Ajax.Request(url, {
        onSuccess: function(response) {
            if (response.responseText.substring(0, 8) === "SUCCESS:")
{
                data = response.responseText.substring(8);
            }
            else {
                data = null;
            }
        },
        onComplete: function() {
            callback(data);
        }
    });
}

Here's what happens when we call this version of `foo`:

1. We start a new Ajax request.
2. `foo` returns.
3. At some point in the future, the Ajax call completes. If it's
successful at the HTTP level (e.g., the response code is 2xx),
Prototype will call the `onSuccess` handler. Our handler checks the
response text to see if the call worked at the business logic level
(remember our values are "SUCCESS:data" or "ERROR"), and if it was
successful we set `data` to the data from the string; if it wasn't, we
set `data` to `null`.
4. When the Ajax call completes (regardless of whether it succeeds or
fails at the HTTP level), Prototype calls the `onComplete` handler. We
call the callback function the caller provided, passing in `data`. If
the Ajax request failed at the HTTP level (404, 500), we'll have never
set `data` *at all* and so it will be `undefined`. If the Ajax request
succeeded at the HTTP level but failed at the business logic level, we
set `data` to `null` in the `onSuccess` handler and so it will be
`null`. If everything worked, `data` will be the data from the
response.

So the documentation of our `foo` function would say that the callback
will *always* be called back, and will be called back with one of
three values:

* undefined: The Ajax call failed at the HTTP level
* null: The Ajax call succeeded but the server returned an error
* a string: The call was successful and this is the data retrieved

Now, you probably wouldn't design an API like that (I wouldn't), but I
wanted to cover the various ways that `data` is or isn't populated.
I'd probably design the API so that the callback received an object
with properties saying what happened, something vaguely like this:

function foo(url, callback) {
    var result;

    result = {
        success: false,
        message: "unknown HTTP error",
        data:    undefined
    };
    new Ajax.Request(url, {
        onSuccess: function(response) {
            var text = response.responseText || "";
            if (text.substring(0, 8) === "SUCCESS:") {
                result.success = true;
                result.message = undefined;
                result.data    = text.substring(8);
            }
            else {
                if {text.substring(0, 6) === "ERROR:") {
                    result.message = text.substring(6).strip();
                }
                else {
                    result.message = "";
                }
                if (!result.message) {
                    result.message = "unknown app error";
                }
            }
        },
        onFailure: function(response) {
            result.message = "HTTP failure code " + response.status;
        },
        onComplete: function() {
            callback(result);
        }
    });
}

Now the callback always gets an object, which the caller can easily
check for success or failure and (if desired) get more information
about the failure if there was one.

I will just mention in passing that it's possible to make an Ajax
request synchronous instead of asynchronous, but I haven't discussed
it above because it's a very, very bad idea. Doing a synchronous Ajax
request locks up the browser while the request is in progress. The
degree to which it locks up the browser varies depending on which
browser you're talking about, but (for instance) on the most common
browser in the world (IE) it not only locks up your page, but every
page in every tab. (And most of the others aren't much better,
partially because they basically *can't* be -- if you have any other
JavaScript on the page, they *have* to completely lock it up during a
synchronous request.) It's a Bad Thing(tm), hence my not talking about
doing it. Embrace the event-driven nature of the environment instead.

HTH,
--
T.J. Crowder
Independent Software Engineer
tj / crowder software / com
www / crowder software / com

On Nov 2, 8:05 pm, laurent barre <houpde...@gmail.com> wrote:
> Hi,
>
> It's the fisrt time that I work with javascript and that I use P.O.O.
> javascript.
> I saw some  lessons on javascript, I start to understand.
>
> You are right, my problem isn't "this".
>
> I retried, the problem is in the function "Ajax.Request".
>
> example code :
>
> url : function(object) {
>             new Ajax.Request(
>                     object.php, {
>                         method: object.method,
>                         parameters: {url_analyse : this.value_event},
>                         onComplete: function (xhr, json){
>                               if (json) {
>                                 var str = '';
>                                 json.each(function (item) {
>                                       str += item.reponse;
>                                     });
>                                show_message(str;);
>                               }
>                         },
>                   }
>             );
>         }
>
> If the function "show_message" is in " new Ajax.Request()" , the result
> corresponds to the Request.
> But if  the function "show_message" is outside "new Ajax.Request()" then the
> result corresponds to the previous Request.
> I don't understand why ?
>
> Thank.
> Laurent
>
> 2010/11/2 T.J. Crowder <t...@crowdersoftware.com>
>
>
>
>
>
>
>
> > Hi,
>
> > I'm afraid your question doesn't make a lot of sense, I think a great
> > deal has been lost in translation.
>
> > But `this` is special in JavaScript: It's set entirely by *how a
> > function is called*, not *where a function is defined*. This is
> > different from other languages. More here:
> >http://blog.niftysnippets.org/2008/04/you-must-remember-this.html
> >http://api.prototypejs.org/language/function/prototype/bind/
>
> > HTH,
> > --
> > T.J. Crowder
> > Independent Software Engineer
> > tj / crowder software / com
> > www / crowder software / com
>
> > On Nov 1, 8:14 pm, laurent barre <houpde...@gmail.com> wrote:
> > > Hi,
>
> > > I have a function Ajax.Responders , but i can't catch the paramater
> > "this"
> > > and i can't modify the value of the parameter "this".
>
> > > the result>one : the value is 'url'
>
> > >  >two :  equal *"no_good"*
>
> > > > three : undefined
>
> > > I try to find a solution, I think that in javascript , the transfert of a
> > > global variable(this) is not possible, do you have a solution ? or a
> > > explication ?
>
> > > Code
> > ----------------------------------------------------------------------
>
> > > *this.element = 'url';
> > > this message = 'no_good';
>
> > > trace(this.element);  > one
>
> > > Ajax.Responders.register({
> > >                 onComplete: function (xhr, json){
> > >                   if (json) {
> > >                     var str = '';
> > >                     json.each(function (item) {
> > >                           str += item.reponse;
> > >                         });
> > >                     this.message = str;  > two
> > >                     trace(this.element);  > three
>
> > >                   }
> > >                 }});
>
> > > *
> > > Code
> > > ------------------------------------------------------------------------
>
> > > thanks,
>
> > > Laurent
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Prototype & script.aculo.us" group.
> > To post to this group, send email to
> > prototype-scriptacul...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > prototype-scriptaculous+unsubscr...@googlegroups.com<prototype-scriptaculou 
> > s%2bunsubscr...@googlegroups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/prototype-scriptaculous?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Prototype & script.aculo.us" group.
To post to this group, send email to prototype-scriptacul...@googlegroups.com.
To unsubscribe from this group, send email to 
prototype-scriptaculous+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en.

Reply via email to