1

I'm sending a GET request with jQuery

$.get("/index.html", /*Adding '?update' to the request*/ "update",
function (data) {/* Enter code here */}, "html");

where data is my server's response. I'm sending back a simple script like alert() so the 'data' variable equals <script> alert("Hello world!") </script>.

I need a way to automatically execute the script. I could just .append(data) to an element but I'm having multiple appends so that isn't really practical.

What is the easiest and the most practical way of executing the script?

Juubes
  • 21
  • 1
  • 8
  • 1
    Easiest, but *non practical* is to get rid of ` – drinchev Aug 11 '17 at 14:44

2 Answers2

3

Either .append it, like you said, or use eval(data), but then you'd have to get rid of the <script></script>. You can supply eval() a piece of Javascript code and it will execute that.

Please be aware that using eval should be avoided at all costs.

Jeff Huijsmans
  • 1,388
  • 1
  • 14
  • 35
2

I did some crazy stuff in a case like this but you may think it is extreme. In my case I had to store some functions in localStorage and execute them by history state ( when user goes back/forth ). I have created a json object similar to

{obj:'myObject', fn: 'myfn', args: myArgs} 

then stored this data base64 encoded. then when I need it back, I simply decoded content and

window.[data.fn].[data.obj].apply(null,data.args)`

did the trick without exposing too much data and not using eval. Eval comes from Evil so I would stay away. =)

UPDATE

So in my case all main core functions are json objects at window namespace similar to ( not actual content but an sample)

Member = {  
   initialize: function (){
          //some process
   }, 
   render:function(memberId, selector){
          //Some process
   },
   //...etc }

So when I store each item it, I used something similar to

var data = {obj: 'Member', fn: 'render', args: [1,'#member-block']}

then encoded version will be

localStorage.setItem('data', btoa(JSON.stringify(data)));

dmFyIGRhdGEgPSB7b2JqOiAnTWVtYmVyJywgZm46ICdyZW5kZXInLCBhcmdzOiB7bWVtYmVySWQ6MSwgc2VsZWN0b3I6ICcjbWVtYmVyLWJsb2NrJ319

Then when I need to call back

var data = JSON.parse(atob(localStorage.getItem('data'));

would return my original data object. Since the main functions in my case are in window namespace.

 if (typeof window[data.obj]!=='undefined') { // same as window.Member 
     if (typeof window[data.obj][data.fn]!=='undefined' && typeof window[data.obj][data.fn]!=='function' ) { // make sure fn is defined and is a function
          window[data.obj][data.fn].apply(null, data.args); 
          // we pass same arguments to function call with apply. 
          // `apply` will give us option to add arguments dynamically without knowing its size. 
          // it can be null any number of arguments that needed for that function. 
     }
 }
serdar.sanri
  • 2,217
  • 1
  • 17
  • 21
  • looks like a very neat one there, I'll give it a try. – jidexl21 Aug 11 '17 at 15:08
  • But also keep in mind that if your arguments include any type of function (like callbacks and stuff ) then they will disappear on JSON.stringify in order to create a base64 content. to avoid that I used `JSON.stringify(obj, function(data){ }) ` and converted functions in arguments into string by toString() method, and did same on JSON.parse . – serdar.sanri Aug 11 '17 at 15:23
  • a simple approach based on your solution would be to send a json response and .apply to run the function, with the downside of exposing a little too much. I think that would be a perfect solution the OP needs. but do u mind explaining this bit window.[data.fn].[data.obj].apply(null,data.args) – jidexl21 Aug 11 '17 at 15:43