Search code examples
javascriptjsonangularjsnode.jsswig-template

More efficient way to interpret data from route in view with Angular over Swig?


I have an array of JSON objects being passed from my Node route into its respective view. For example:

res.render("path/to/view", { data: result, data2: result2 })

where both result and result2 are arrays of JSON objects. In my view, I am using them in an ng-init function like so: ( {{}} designates swig, where I have changed [[]] to designate Angular, so in the below example, we are using swig before using my defined Angular init function)

<div ng-init="init( {{ data|json }} )"> </div>

I should say that the above example works fine, but when "data" becomes a very large dataset, SO much time is spend on the swig part - that is converting it to JSON (again..?). Like I said, the "data" is already in the form of JSON, but when I remove the |json from the swig part above, I get a [$parse:syntax] error, and it give me the above line but evaluated:

<div ng-init="init( [object Object],[object Object] )"> </div>

I have tried variations of using ng-init="init( [[ JSON.parse( {{ data }} ) ]] )" so that I evaluate the output to JSON (even though the output already is..?) but cant get anything to work.

Any ideas? Maybe I have the syntax wrong? I don't understand because the "data" is JSON when I pass it to the view, but I can't pass it directly into my init function without getting that syntax error.


Solution

  • So while I am not entirely sure what was causing it to go so slow, I have found a solution, although 'hack' might more accurately describe it. The problem I was having was with Swig taking ages to template my data before passing it into the init function (which I now know is bad practice; that is, to use ng-init to call a function).

    I should note for future readers that I am using Node.js, Swig for templating, and Angular for handling the the MVC side of things.

    See the above question to see what my code was like before (slow version). Below is my solution:

    Routing side

    var rawSQLData = makeSQLCall();
    var parsedAsJsonSQLData = parseData(rawSQLData);
    var parsedDataAsString = JSON.stringify(parsedAsJsonSQLData);
    res.render("path/to/view", { data: parsedDataAsString });
    

    HTML

    <div ng-init=" init( {{ data|json }} )">   </div>
    

    Angular Controller

    $scope.init = function(data){
        $scope.dataInScope = JSON.parse(data);
    }
    

    As you can see, the only thing I changed was stringifying the JSON before shooting it to the HTML and then parsing it once it gets to the controller.

    The reason I think this works is because I am essentially doing all of the JSON processing in parts other than the templating engine (Swig). I tried using no filter, but Swig defaults to converting the data to JSON which was breaking my HTML. The reason that I want to call this a hack rather than a solution is because we stringify the data, and then use the json filter for Swig, which, according to the documentation:

    Return a string representation of an JavaScript object.

    If I had to guess, I would say that by using the json filter on a string, Swig decides it has nothing to do as the object is already a string and just passes it along (just what I wanted all along!). It is incredible how much faster it is when Swig doesn't touch the data. The JSON stringify and parse are really quick for the size of data, while Swig was taking up to 40 seconds