Shoutbox

AJAX isn't working - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: AJAX isn't working (/showthread.php?tid=95348)

AJAX isn't working by The-Phantom on 08-28-2010 at 01:33 PM

Sometimes, when I do an AJAX request, it just stays at the readyState of 1, thereby hanging WLM. Sometimes, however, it doesn't happen. I can still access the page by browsing to it via a browser, so it's not a network problem. What's happening?


RE: AJAX isn't working by V@no on 08-29-2010 at 05:31 AM

I think there would be much better chance get a good answer if you'd post the AJAX code you are using...


RE: AJAX isn't working by The-Phantom on 08-29-2010 at 07:09 AM

Okay. I've made a simple script to demonstrate it. Here's the only JS file:

var xhr;
var ready;
function OnEvent_ChatWndSendMessage(Wnd, Message)
{
    if(Message.substr(0, 10) != "/ajax-test")
        return "";
    Debug.Trace("Retrieving " + Message.substr(11));
    var Iter = 0;
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
    xhr.open("GET", encodeURI(Message.substr(11)), true);
    xhr.onreadystatechange = function()
    {
        if(xhr.readyState == 4)
            ready = true;
    };
    ready = false;
    xhr.send();
    while(!ready)
        // If I don't check for this here, it just hangs up because ready is always false and this becomes an infinite loop
        if(Iter++ > 10000000)
        {
            Debug.Trace("Error.");
            return "";
        }
    Debug.Trace(xhr.responseText);
    return "";
}

With the appropriate ScriptInfo.xml, I've tested it with several URLs, and here are the results:

Function called: OnEvent_ChatWndSendMessage
Retrieving http://example.com/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
  <META http-equiv="Content-Type" content="text/html; charset=utf-8">
  <TITLE>Example Web Page</TITLE>
</HEAD>
<body> 
<p>You have reached this web page by typing &quot;example.com&quot;,
&quot;example.net&quot;,&quot;example.org&quot
  or &quot;example.edu&quot; into your web browser.</p>
<p>These domain names are reserved for use in documentation and are not available
  for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC
  2606</a>, Section 3.</p>
</BODY>
</HTML>


Function called: OnEvent_ChatWndSendMessage
Retrieving http://www.example.com/
Error.
Function called: OnEvent_ChatWndSendMessage
Retrieving http://www.msgplus.net/
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta name="norton-safeweb-site-verification"
...
</div>

</body>
</html>

Function called: OnEvent_ChatWndSendMessage
Retrieving http://www.google.com/
Error.


RE: AJAX isn't working by Matti on 08-29-2010 at 07:10 PM

Since you want to modify the sent message, you need to use a synchronous XMLHTTP request as opposed to an asynchronous request. You need to modify the return value of OnEvent_ChatWndSendMessage, so your script has to wait for the result before continuing execution.

This cannot and should not be done with an infinite loop!!! Your loop essentially blocks the entire Messenger thread, including the onreadystatechange callback!

js code:
function OnEvent_ChatWndSendMessage(Wnd, Message)
{
    if(Message.substr(0, 10) != "/ajax-test")
        return "";
    Debug.Trace("Retrieving " + Message.substr(11));
    var xhr = new ActiveXObject("Microsoft.XMLHTTP");
    // Note the 3rd argument: async = false, thus send() returns immediately
    xhr.open("GET", encodeURI(Message.substr(11)), false);
    xhr.send();
    if(xhr.status === 200) { // HTTP 200 OK
        // Success!
        Debug.Trace(xhr.responseText);
    } else {
        // Something went wrong...
        Debug.Trace("Error.");
    }
    // Return empty message
    return "";
}
Tip: wrap your code blocks in [code=js]...[/code] tags for beautiful JavaScript syntax highlighting! :D

RE: AJAX isn't working by The-Phantom on 08-29-2010 at 07:57 PM

That works perfectly! Huge thanks! [Image: jumpy.gif]


RE: AJAX isn't working by CookieRevised on 08-29-2010 at 08:24 PM

quote:
Originally posted by The-Phantom
That works perfectly! Huge thanks! [Image: jumpy.gif]
sorry, but what Matti posted should not be done unless you want to slow down Messenger...

--------------

quick note to Matti first:

Matti, shouldn't that be:

// Note the 3rd argument: async = false, thus send() does not return immediately

The whole point of a synchronous call is exactly that send() will not return immediatly; it will wait until the whole thing is retrieved and thus it will slow down, if not lock up, Messenger!

Only when you have an asynchronous call, the send will return immediatly (and hence the reason why he had to make (bad) use of that loop)....

--------------

So, I do very highly recommend using an asynchronous method though! And actually advise against using a synchronous (async=false) method like Matti suggested.

By using a synchronous you will always end up slowing down and even locking up Messenger in one way or the other.

So, the problem you had is not because of the asynchronous call, but because you did not properly used the return function. Do not return (or wait to return) some text in the OnEvent_ChatWndSendMessage itself! That is not the proper way of doing things.

What you should be doing is:

1) in OnEvent_ChatWndSendMessage:
   a) make the asynchronous call and assign another function to the onreadystatechange property
   b) return ""
2) And only inside that other function which got assigned to onreadystatechange (and thus NOT outside this function like you did before with that loop), you do what you want to do.

Also note: in case you want to send some text back to the chat window in response to the outcome of the http call, check if the chat window still exists (highly important), then check if you actually can send some text. After that send the text you want with SendMessage... But all this also requires some additional scripting including keeping track of chat window objects and the contacts within the chats! So you will need to create and maintain an array on the global scope of the script too. And chats with more than one person will make this rather complicated though.

js code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    if (Message.substr(0, 10) === "/ajax-test") {
        Debug.Trace("Retrieving " + Message.substr(11));
        var xhr = new ActiveXObject("Microsoft.XMLHTTP");
        xhr.open("GET", encodeURI(Message.substr(11)), true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    Debug.Trace("html: " + xhr.responseText);
                } else {
                    Debug.Trace("error: " + xhr.status);
                }
            }
        }
        xhr.send();
        return ""
    }
}
Although I suspect that you better assign the XMLHTTP object in the global scope though. Can't be bothered checking on how Plus! handles such stuff/objects when used asynchronously...

---------

Also:
quote:
Originally posted by The-Phantom
js code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    if (Message.substr(0, 10) != "/ajax-test") return "";
    // your code for the command /ajax-test here
}

That is very wrong and you should never be doing this. You cripple the proper workings of command handling by that. You should be doing the opposite:
js code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    if (Message.substr(0, 10) === "/ajax-test") {
        // your code for the command /ajax-test here
        return "";
    }
}
Note that there is no Return outside the IF statement.
RE: AJAX isn't working by Matti on 08-29-2010 at 08:43 PM

Crap, Cookie beat me again. :P

I knew it would be impossible to return a value from within an asynchronous onreadystatechange callback, so I went with a synchronous call, which is basically just another way to block Messenger. I must agree that it is much better to just return an empty string when the command is captured and send something whenever the request finishes (without using the return value to send a message). My solution isn't really a solution, your solution is far superior. :)

And yes, that command parsing is very bad, basically you're pushing all the other commands and scripts out of the way and only let your command through. Not good.

* Matti needs some coffee...


RE: AJAX isn't working by The-Phantom on 08-30-2010 at 06:48 AM

Yeah, I know about that error of mine. But can't it be like this?

js code:
function OnEvent_ChatWndSendMessage(Wnd, Message)
{
    if(Message.substr(0, 10) != "/ajax-test")
        return Message;
    // handling for /ajax-test
}

Also, I know that I can do the same with an asynchronous request and sending another message, but what about receiving messages, where I need to change the text I receive? There's no function to "receive" another command, as far as I am aware…
RE: AJAX isn't working by CookieRevised on 08-30-2010 at 08:31 AM

quote:
Originally posted by The-Phantom
Yeah, I know about that error of mine. But can't it be like this?
js code:
function OnEvent_ChatWndSendMessage(Wnd, Message)
{
    if(Message.substr(0, 10) != "/ajax-test")
        return Message;
    // handling for /ajax-test
}

No...
1) nothing will be executed after the return statement
2) when you return the same message, the command will be send to your contact too (as text).
3) in that code you check if the message is _not_ "/ajax-test", it should be the opposite. You should never ever do != or !== to check for a command!! Again, this will cripple the proper workings of command handling... Always do a positive test, never a negative, for this.

See the code in my previous post for the proper way.

quote:
Originally posted by The-Phantom
Also, I know that I can do the same with an asynchronous request and sending another message, but what about receiving messages, where I need to change the text I receive? There's no function to "receive" another command, as far as I am aware…
There are some things you need to know whenyou want to change recieved text.

Biggest thing is that you can never change recieved text to text which is longer than the original.

Second, text you receive also includes your own send messages.

See OnEvent_ChatWndReceiveMessage event.

All this is also explained in the Plus! Scripting documents.

;)
RE: RE: AJAX isn't working by The-Phantom on 08-30-2010 at 08:40 AM

quote:
Originally posted by CookieRevised
No...
1) nothing will be executed after a return statement
2) when you return the same message, the command will be send to your contact too (as text).
3) in that code you check if the message is _not_ "/ajax-test", it should the opposite.

See the code in my previous post for the proper way.

I still don't get it. If it is the command I need, the if clause is skipped and the handling is performed. If it is not, the message is not changed and handling isn't executed. That's exactly the behaviour needed, isn't it?

quote:
There are some things you need to know whenyou want to change recieved text.

Biggest thing is that you can never change recieved text to text which is longer than the original.

Second, text you receive also includes your own send messages.

See OnEvent_ChatWndReceiveMessage event.

All this is also explained in the Plus! Scripting documents.

;)

Yes, yes, I know. How could I be able to make some scripts without reading that first?
RE: RE: RE: AJAX isn't working by CookieRevised on 08-30-2010 at 09:01 AM

quote:
Originally posted by The-Phantom
quote:
Originally posted by CookieRevised
No...
1) nothing will be executed after a return statement
2) when you return the same message, the command will be send to your contact too (as text).
3) in that code you check if the message is _not_ "/ajax-test", it should the opposite.

See the code in my previous post for the proper way.
I still don't get it. If it is the command I need, the if clause is skipped and the handling is performed.
No it is not. the handling of the command (that comment block) is placed after the return statement in your code. Anything after a return statement will not get executed.

And, again, you should NEVER perform a negative check (!= or !==) when you want to check for your command, that is realy not the proper way of doing things and it will cripple other stuff. It is also not logical to do it and it requires more code.

Read the scripting documentation about command handling....

The proper way is:
js code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    if (Message.substr(0, 10) === "/ajax-test") {
        // your code for the command /ajax-test here
        return "";
    }
}

quote:
Originally posted by The-Phantom
quote:
There are some things you need to know whenyou want to change recieved text.

Biggest thing is that you can never change recieved text to text which is longer than the original.

Second, text you receive also includes your own send messages.

See OnEvent_ChatWndReceiveMessage event.

All this is also explained in the Plus! Scripting documents.

;)
Yes, yes, I know. How could I be able to make some scripts without reading that first?
You would be surprised to know how many people start scripting without properly reading the docs (and then comming here for help) :P Anyways, I posted that because you asked about changing recieved text. Those are the basics to know for doing that. If that is not what you wanted then I misunderstood you. In that case, could you maybe rephrase your question? Or explain in a detailed way what it is that you exactly want to with all of this.


;)
RE: RE: RE: RE: AJAX isn't working by The-Phantom on 08-30-2010 at 09:22 AM

quote:
Originally posted by CookieRevised
No it is not. the handling of the command (that comment block) is placed after the return statement in your code. Anything after a return statement will not get executed.

I thought that a return statement stops the further code from execution only if that return statement is executed? So if return is skipped, it doesn't stop the execution?

quote:
And, again, you should NEVER perform a negative check (!= or !==) when you want to check for your command, that is realy not the proper way of doing things and it will cripple other stuff. It is also not logical to do it and it requires more code.

Okay, I'll note that (even though I don't exactly understand the reasons).

quote:
You would be surprised to know how many people start scripting without properly reading the docs (and then comming here for help) :P Anyways, I posted that because you asked about changing recieved text. Those are the basics to know for doing that. If that is not what you wanted then I misunderstood you. In that case, could you maybe rephrase your question?

;)

Well, I meant that it is impossible to have a message appear as "received" even though I didn't actually receive it.
RE: AJAX isn't working by Eljay on 08-30-2010 at 09:41 AM

The way that your code is structured is fine, obviously return will not be executed and execution of that function will continue so I don't know what Cookie is on about there :P (I actually prefer coding like that, much easier to read and debug without everything being needlessly nested).

I'm not sure exactly how things work internally, but surely just returning the original message is the same as not returning anything? (If not, it's very illogical but I can see how that might break things). The way you had it originally (return "") was wrong and will stop the message being sent completely, but returning the original message SHOULD be fine.


RE: AJAX isn't working by CookieRevised on 08-30-2010 at 10:12 AM

quote:
Originally posted by Eljay
The way that your code is structured is fine, obviously return will not be executed and execution of that function will continue so I don't know what Cookie is on about there :P (I actually prefer coding like that, much easier to read and debug without everything being needlessly nested).
After you posted I looked at his proposed code again (several times)... Only after like 5 times looking at those few lines of coding, I realized I made a mistake.

But this was exactly because he did NOT nested the if structure between brackets { }. So reading and debugging made easier if you don't nest stuff? I realy dont think so... It's more confusing and mistakes happen more quickly, especially when you split things out on several lines. (and reading other scripting topics, such mistakes happen all the time)... edit: see again here (and I can probably keep on updating with more links regulary)...

But thanks for pointing out my mistake. (y)

So, yes, using a negative check like that and returning the _original_ message will work, but besides I think it is not logic to do, it does make code more confusing and execution slower (you should not notice it though)...

Furthermore, the moment you want to make your check a bit better (eg: taking in account the casing of the command, and other tid bits), use regular expressions, want to use more than one command, or want to check on other things too (eg: who the contact is or whatever), your code quickly becomes more confusing and harder to follow if you use a negative check. And you'll find that you'll quickly revert to a positive check in such cases anyways for such stuff.

quote:
Originally posted by The-Phantom
quote:
You would be surprised to know how many people start scripting without properly reading the docs (and then comming here for help) :P Anyways, I posted that because you asked about changing recieved text. Those are the basics to know for doing that. If that is not what you wanted then I misunderstood you. In that case, could you maybe rephrase your question?

;)
Well, I meant that it is impossible to have a message appear as "received" even though I didn't actually receive it.
So you want to show a kind of status message? Then this doesn't have much to do with changing recieving text. You actually want to _add_ text, if I'm not mistaken.

You indeed can't directly add text to the history window, but you can use DisplayInfoMessage to show a status message in the chat window. Or you can use toasts.
RE: AJAX isn't working by Eljay on 08-30-2010 at 10:35 AM

quote:
Originally posted by CookieRevised
But this was exactly because he did not nested the IF structure between { }. So reading and debugging made easier if you don't nest stuff? I dont think so... it's more confusing and mistakes happen more quickly, especially when you split things out on several lines. (and reading other scripting topics, such mistakes happen all the time)...

I agree it can be harder to read if you omit the braces, but what I meant was, for example, the difference between these two code blocks:

js code:
if(functionA()) {
    if(functionB()) {
        // do something
    }
    else {
        // handle error b
    }
}
else {
    // handle error a
}

// ==========

if(!functionA()) {
    // handle error a
    return;
}
if(!functionB()) {
    // handle error b
    return;
}

// do something

It keeps everything together nicely imo, with the error handling right next to the error. Obviously it might not always be applicable, and everything is open to argument :P

[/off-topic]