Calling a JavaScript function returned from an Ajax response

174,806

Solution 1

I think to correctly interpret your question under this form: "OK, I'm already done with all the Ajax stuff; I just wish to know if the JavaScript function my Ajax callback inserted into the DIV is callable at any time from that moment on, that is, I do not want to call it contextually to the callback return".

OK, if you mean something like this the answer is yes, you can invoke your new code by that moment at any time during the page persistence within the browser, under the following conditions:

1) Your JavaScript code returned by Ajax callback must be syntactically OK;
2) Even if your function declaration is inserted into a <script> block within an existing <div> element, the browser won't know the new function exists, as the declaration code has never been executed. So, you must eval() your declaration code returned by the Ajax callback, in order to effectively declare your new function and have it available during the whole page lifetime.

Even if quite dummy, this code explains the idea:

<html>
    <body>
        <div id="div1">
        </div>
        <div id="div2">
            <input type="button" value="Go!" onclick="go()" />
        </div>
        <script type="text/javascript">
            var newsc = '<script id="sc1" type="text/javascript">function go() { alert("GO!") }<\/script>';
            var e = document.getElementById('div1');
            e.innerHTML = newsc;
            eval(document.getElementById('sc1').innerHTML);
        </script>
    </body>
</html>

I didn't use Ajax, but the concept is the same (even if the example I chose sure isn't much smart :-)

Generally speaking, I do not question your solution design, i.e. whether it is more or less appropriate to externalize + generalize the function in a separate .js file and the like, but please take note that such a solution could raise further problems, especially if your Ajax invocations should repeat, i.e. if the context of the same function should change or in case the declared function persistence should be concerned, so maybe you should seriously consider to change your design to one of the suggested examples in this thread.

Finally, if I misunderstood your question, and you're talking about contextual invocation of the function when your Ajax callback returns, then my feeling is to suggest the Prototype approach described by krosenvold, as it is cross-browser, tested and fully functional, and this can give you a better roadmap for future implementations.

Solution 2

Note: eval() can be easily misused, let say that the request is intercepted by a third party and sends you not trusted code. Then with eval() you would be running this not trusted code. Refer here for the dangers of eval().


Inside the returned HTML/Ajax/JavaScript file, you will have a JavaScript tag. Give it an ID, like runscript. It's uncommon to add an id to these tags, but it's needed to reference it specifically.

<script type="text/javascript" id="runscript">
    alert("running from main");
</script>

In the main window, then call the eval function by evaluating only that NEW block of JavaScript code (in this case, it's called runscript):

eval(document.getElementById("runscript").innerHTML);

And it works, at least in Internet Explorer 9 and Google Chrome.

Solution 3

It is fully possible, and there are even some fairly legitimate use cases for this. Using the Prototype framework it's done as follows.

new Ajax.Updater('items', '/items.url', {
    parameters: { evalJS: true}
});

See documentation of the Ajax updater. The options are in the common options set. As usual, there are some caveats about where "this" points to, so read the fine print.

The JavaScript code will be evaluated upon load. If the content contains function myFunc(), you could really just say myFunc() afterwards. Maybe as follows.

if (window["myFunc"])
   myFunc()

This checks if the function exists. Maybe someone has a better cross-browser way of doing that which works in Internet Explorer 6.

Solution 4

That seems a rather weird design for your code - it generally makes more sense to have your functions called directly from a .js file, and then only retrieve data with the Ajax call.

However, I believe it should work by calling eval() on the response - provided it is syntactically correct JavaScript code.

Solution 5

With jQuery I would do it using getScript

Share:
174,806
William Troup
Author by

William Troup

Software Engineer/Architect, writer, designer, etc

Updated on July 05, 2022

Comments

  • William Troup
    William Troup about 2 years

    I have a system where I send an Ajax command, which returns a script block with a function in it. After this data is correctly inserted in the DIV, I want to be able to call this function to perform the required actions.

    Is this possible?

  • Matthias Kleine
    Matthias Kleine about 9 years
    This is aweome! Thanks! I've always used the "onSuccess" function on the updater to eval the Javascript manually. But this is more readable and works in all browser.
  • mwild
    mwild about 9 years
    Amazing, been trying to figure this out for a while +1
  • Bryan Zwicker
    Bryan Zwicker about 9 years
    I've been trying to solve this for hours and just came across this answer! This is awesome and should probably be the accepted! Thank you, +1 :)
  • Savas Vedova
    Savas Vedova about 9 years
    Is there any security hole in implementing this solution?
  • Typel
    Typel over 8 years
    This works in the example because everything is in the same page and timing doesn't come into play. It doesn't work with anything that actually utilizes AJAX methodologies to call external files for processing because the eval() function runs before the external process has any time to return with a response.
  • Manish
    Manish over 7 years
    Superb answer really save my time. God bless you.
  • Anupam
    Anupam about 7 years
    @Typel Any security risks of using eval() here?
  • Typel
    Typel about 7 years
    @Anupam I think the general consensus is that eval() always has security risks associated with it - I would be be mindful how and if it gets used. Personally, I wouldn't use it in conjunction with AJAX to avoid opening any XSS vulnerabilities. In most cases if I need a function to execute from an AJAX return, I would just pass the arguments back instead and let the meat of the function reside in and execute from the calling page instead (or something similar).
  • Jan Bradáč
    Jan Bradáč over 5 years
    Still actual in 2018: This sounds dangerously like "Security by obscurity". If I was attacking your site and noticed that eval() function, then I would surely notice the ID tag there and modify my attack to just insert the malicios code inside your <script id="my-secure-id"> tag. I do not see any added security by using this solution. In fact, it only gives you the false sense of security, which is even more dangerous. But some 6 years later, HTTPS is now very much more common. I beleive that an attack on eval() should not be possible over secure HTTPS. Am I wrong assuming that?
  • Joel M
    Joel M over 4 years
    Obviously eval is dangerous in some contexts, but if someone were to intercept your code assuming your not running over ssl and inject some code into eval is there any legitimate reason why they couldn't do the same thing if your response return HTML which is inserted into the DOM (they can just add a script tag to it). It seems to me that running eval on a response from the server has the same security implications as the server giving you HTML that you insert into the DOM. Perhaps there is some difference though.
  • alvaroc
    alvaroc over 3 years
    He is not asking weather or not is a good idea, he is asking if it is possible