1

I'm trying to use this AJAX request to call a file with some PHP which is working ok and some JavaScript which is not. any ideas?

function showpart2(){
    if(window.XMLHttpRequest){
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET","atuamae.org/parte2-encomendar.php",false);
        xmlhttp.send(null);
    }

    document.getElementById('part2').innerHTML = xmlhttp.responseText;
    eval(xmlhttp.responseText.getElementById('part2').innerHTML)

    setTimeout('showpart2()',15000);

}

showpart2();
6
  • 4
    I know this isn't really an answer, so I'll put it as a comment, but jQuery, if you have the ability to add it to your site, can greatly simplify your ajax-calling needs. api.jquery.com/category/ajax Commented Nov 25, 2011 at 17:45
  • 2
    it is possible. but it is a bad idea to use eval. Commented Nov 25, 2011 at 17:48
  • If the response data is JavaScript code, place it in a SCRIPT element and append that element to the DOM... Commented Nov 25, 2011 at 17:49
  • 1
    Your code is broken, your using synchronous XHR (which is the devil) Commented Nov 25, 2011 at 17:49
  • 1
    "does not work" is a bad statement in a question, please update it : what does the php file return? why do you want to eval it in first place? what is not working? .. oh , and ignore the jquery people. Commented Nov 26, 2011 at 7:43

4 Answers 4

1

One big problem with the sample code is that making XMLHttpRequest.send synchronous means all JS execution must pause while waiting for the request to be received. There's no reason not to use an asynchronous call.

Asynchronous calls can improve responsiveness, but what they don't give you is coordination, which means a task won't run until the data it needs is ready. The standard way of coordinating asynchronous code is to pass to the asynchronous function a function that, when executed, performs the rest of the computation that relies on the data. This function has the technical name "continuation", which is simply a function that represents the rest of the computation from a given point forward. That is, turn:

f1();
f2();
async();
f3();
f4();

into:

f1();
f2();
async(function() {
    f3();
    f4();
});

Because you're passing around a continuation, this is known as "continuation passing style". XMLHttpRequest is a special case in that rather than passing a function to the asynchronous function, you set it as a listener for the readystatechange event on the XHR object. That is, you assign the continuation to xmlhttp.onreadystatechange.

There are a few more improvements to make. First, add error detection. The status property of the XHR instance holds the HTTP status, which you can use to check for errors.

As a number of others have mentioned, eval can be problematic and should be avoided when there's another option. For one thing, you have to make sure the string comes from a trusted source. The particular problem with eval here is that the script is evaluated in the same context as the call to eval. If the eval happens inside a function, anything defined by the script isn't visible outside the function. If your script doesn't need to define anything (and will never need to define anything; always consider the future of your code), you can use eval. Otherwise, dynamically create a script element with the script as content and add it to the document; you can define a function that does this (see globaleval in the sample below).

xmlhttp is a global variable, which is bad. Instead, declare it as a local variable.

Rather than setTimeout, which is for one-shot calls, use setInterval, which calls the passed function periodically. Note that both setTimeout and setInterval may take longer than the given delay to run, though that shouldn't be an issue here.

(function () {
    // keep variable from polluting global namespace
    var showpart2Interval = 0,
        scriptElt = {parentNode: {removeChild: function() {}}};
        
    function globaleval(script) {
        scriptElt.parentNode.removeChild(scriptElt);
        scriptElt = document.createElement('script');
        scriptElt.type = 'text/javascript'
        scriptElt.appendChild(document.createTextNode(script));
        document.body.appendChild(scriptElt);
    }

    function showpart2(){
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET","atuamae.org/parte2-encomendar.php",false);
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4) {
                if (200 <= xmlhttp.status && xmlhttp.status < 300) {
                    globaleval(xmlhttp.responseText);
                } else {
                    // HTTP error
                    ...
                }
            }
        }
        xmlhttp.send(null);
    }
    
    function startShowpart2() {
        if (window.XMLHttpRequest && !showpart2Interval) {
            showpart2();
            showpart2Interval = setInterval(showpart2, 15000);
        }
    }
    function stopShowpart2() {
        clearInterval(showpart2Interval);
        showpart2Interval = 0;
    }
    
    window.startShowpart2 = startShowpart2;
    window.stopShowpart2 = stopShowpart2;
})();

startShowpart2();

If you don't care about implementing all of this yourself, have jQuery do the heavy lifting. It's good to know how to do things yourself, but (for production code) using standard libraries with standard interfaces speeds up development in a number of ways.

See also

Sign up to request clarification or add additional context in comments.

Comments

0

You need to actually evaluate the JS-tags (manually, either through eval or through DOM insertion). A library like jQuery would do this for you, but if you need to use a custom solution you'll need to add that as well.

1 Comment

I believe he means <script> tags.
0

You write:

xmlhttp.responseText.getElementById('part2')

The responseText is a string, and won't have any getElementById method. You either want to use xmlhttp.responseXML.getElementById("part2") or use string methods to extract the second part.

Comments

0

Like Adam Rackis I recommend you use $.ajax is reallyyyy easy try it.....but if it is not an option for you here is a function as used to use when making ajax calls and worked in IE and Firefox, Chrome I recommend to you if you can not use Jquery. The problem in your function not works in IE as it has no xmlhttprequest object. Hope this helps you.

function newAjaxObject()
{
    var oHttp=false;
    var asParsers=[
         "Msxml2.XMLHTTP.5.0", 
         "Msxml2.XMLHTTP.4.0", 
         "Msxml2.XMLHTTP.3.0", 
         "Msxml2.XMLHTTP", 
         "Microsoft.XMLHTTP"
    ];

    if ( !oHttp && typeof XMLHttpRequest != 'undefined')
    {
        oHttp=new XMLHttpRequest();
    }

 if( !oHttp){
    for (var iCont=0; !oHttp && iCont < asParsers.length; iCont++)
    {
        try
        {
            oHttp=new ActiveXObject(asParsers[iCont]);
        }
        catch(e)
        {
            oHttp=false;
        }
    }
}

   return oHttp;
}

2 Comments

solved it with jquery so fast!!!! thanks for your quick responses! you huys are amazing. this is what i did: <script type="text/javascript"> function showpart2(){ $("#part2").load('atuamae.org/parte2-encomendar.php'); setTimeout('showpart2()',15000); }; showpart2(); </script>
you are doing it a bit wrong. As the latest IE's too have XMLHttpRequest , you should at first check for that. Additionally, if visitor is not using IE, your loop there is wasteful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.