This is a migrated thread and some comments may be shown as answers.

Data Source - Schema - Parse function error when creating new Function

5 Answers 76 Views
Data Source
This is a migrated thread and some comments may be shown as answers.
Dominik
Top achievements
Rank 1
Dominik asked on 31 Jul 2015, 04:07 AM

using the following constructor in the parse function throws an exception:

new Function("args", body);

"Uncaught SyntaxError: Unexpected identifierkendo.data.DataSource.schema.parse @ KendoWorklist?processId=1:257g.extend.success @ kendo?v=eOyB53xLlSdFHOrBbggvVxenL4FmfrA-viibHS3DbGs1:1g.extend.read.i._queueRequest.i.online.i.transport.read.success @ kendo?v=eOyB53xLlSdFHOrBbggvVxenL4FmfrA-viibHS3DbGs1:1vt.extend.read.i.success @ kendo?v=eOyB53xLlSdFHOrBbggvVxenL4FmfrA-viibHS3DbGs1:1i.Callbacks.a @ jquery?v=FVs3ACwOLIVInrAl5sdzR2jrCDmVOWFbZMY6g6Q0ulE1:1i.Callbacks.h.fireWith @ jquery?v=FVs3ACwOLIVInrAl5sdzR2jrCDmVOWFbZMY6g6Q0ulE1:1k @ jquery?v=FVs3ACwOLIVInrAl5sdzR2jrCDmVOWFbZMY6g6Q0ulE1:1i.ajaxTransport.send.u @ jquery?v=FVs3ACwOLIVInrAl5sdzR2jrCDmVOWFbZMY6g6Q0ulE1:1"

why would the new Function constructor not work in the parse function?

5 Answers, 1 is accepted

Sort by
0
Dominik
Top achievements
Rank 1
answered on 31 Jul 2015, 01:29 PM

the reason I want to use the new Function() constructor is because I send my data over normalized and the most efficient way to denormalize it is as follows:

 

// My starting Normalized data
var fields = ["name","age"];
var data2 = [["John",20],["Tom",25]];
  
  
// What I want the result to look like Denormalized
var data1 = [{"name":"John", "age":20},{"name":"Tom", "age":25}];
  
  
// Solution 1 O(N^2) --- this is slow
  
var fields = ["name","age"];
var data2 = [["John",20],["Tom",25]];
var data1 = [];
for(var i = 0; i < data2.length; i++){
    
var temp = {};
    
for(var y = 0; y < fields.length; y++){
       
temp[fields[y]] = data2[i][y];
    
}
    
data1.push(temp);
}
  
  
// solution 2 O(N)
  
var fields = ["name","age"];
var data2 = [["John",20],["Tom",25]];
var body = "";
  
for(var i = 0; i < fields.length; i++){
    
body += "this."+fields[i] +"=args["+i+"]; ";
}
  
var model = new Function("args",body);
  
var data1 = [];
for(var i = 0; i < data2.length; i++){
    
var x = new model(data2[i]);
    
data1.push(x);
}

0
Vasil
Telerik team
answered on 03 Aug 2015, 01:54 PM
Hello Dominik,

I think both solutions have the same complexity O(N*M);

Where N is the count of the data.
And M is the count of the fields.

Additionally the const of the both approaches is pretty much the same.

The difference is that in first approach you iterate the properties and build the object yourself. And in the second approach you pass some big constructor for this object, and the JS engine parses the values and then the browser do the same: iterate them and build the object. 

If you perform some test, you will get very similar times in both large and small set of data. Here is some code based on yours:
var fields = [];
var data2 = [];
 
 
for (var j = 0 ; j < 1000; j++) {
    fields.push("a" + j + "r" + Math.floor(Math.random() * 100));
}
 
for (var i = 0; i < 10000 ; i++) {
    var item = [];
    for (var j = 0 ; j < 100; j++) {
        item.push(Math.random());
    }
    data2.push(item);
}
 
var data1;
 
function f1() {
    data1 = [];
 
    data1.length = data2.length;
    var temp;
 
    for (var i = 0; i < data2.length; i++) {
        temp = {};
        for (var y = 0; y < fields.length; y++) {
            temp[fields[y]] = data2[i][y];
        }
        data1.push(temp);
    }
};
 
function f2() {
    var body = "";
    for (var i = 0; i < fields.length; i++) {
        body += "this." + fields[i] + "=args[" + i + "]; ";
    }
 
    var model = new Function("args", body);
 
    data1 = [];
    data1.length = data2.length;
    for (var i = 0; i < data2.length; i++) {
 
        var x = new model(data2[i]);
        data1.push(x);
    }
};

The times that I get are 2.478s for the first function and 2.264 for the second for this very big set of data. For small set of data they work practically the same.

From profiling in chrome it seems that the difference comes mainly from execution of the garbage collector more often in the first function.

So you can use the working approach without any worries. I will additionally debug why the second one fails when passed as a parse function.

Regards,
Vasil
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Dominik
Top achievements
Rank 1
answered on 03 Aug 2015, 05:36 PM
Thank you for looking into this for me!  Technically the first solution is (M*N) and the second solution is (M+N). For simplicity I used (N^2) and (N). But you're right, for small amounts of data there is little to no difference. 
0
Dominik
Top achievements
Rank 1
answered on 03 Aug 2015, 06:27 PM

also instead of concatenating with "+=" I should've used ".concat()"

with this change f2() is much master than f1()

0
Vasil
Telerik team
answered on 04 Aug 2015, 07:03 AM
Hi Dominik,

Interesting is that in Firefox (Nightly Builds) the solution 2 is actually slower than solution 1.

Back to the original subject. I tried to get the same error as you, but in my case it is working correct, even with your original code.
Here is testing example in our dojo:
http://dojo.telerik.com/egIsA
When I run it I get the alert displaying the name and age of the first record. And looking at the console, there is no exception like described.

What I see here as the potential problem if the fields contains numbers without literal prefix.
For example if the field is called "123" instead of "name". Then you will get exception when evaluating function like:
"this.123 = something".
however the first solution will work:
this[123] = something

Could you check  the example code above, and tell me what is different in your case. You can edit the example and write here the new link you get.

Regards,
Vasil
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tags
Data Source
Asked by
Dominik
Top achievements
Rank 1
Answers by
Dominik
Top achievements
Rank 1
Vasil
Telerik team
Share this question
or