tbm0115
tbm0115

Reputation: 419

Javascript Large Data Optimization

Background

So, I'm developing an Intranet site that provides documentation for manufacturing operations. Each "document" is a series of data stored in a SQL database, but there are elements of the document that I have needed to create JS Libraries for, which are loaded with the page.

Essentially, these objects are "filled" with a single JS file that is generated by a management application I developed for the desktop. This file is already breaching 3K lines of code and I'm concerned how performance will be once this project is implemented and rolling. I went with using a JavaScript file because it's quick to generate with the management application and it only needs to be generated once in a blue moon (ideally). So, compiling the data in code behind would have adverse affects on performance.

Examples

So far, I've taken the approach of referencing the various objects directly, line-for-line and setting their important values. For example:

var tmpTool;
var tmpChara;
tmpTool = new Tool();
tmpTool.Type = new Type(GRVR.Type.Delem, GRVR.Type.List, GRVR.Type.Case, GRVR.Type.Label, GRVR.Type.AlternateText);
tmpTool.ID = 1200;
tmpChara = tmpTool.AddCharacteristic('#M', 'Material Type', 'Material Type', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('#G', 'Grade Type', 'Grade Type', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('FL', '', 'Functional Length', false);
tmpChara.setValue('0.79');
tmpChara = tmpTool.AddCharacteristic('CW', '', 'Cutter Width', false);
tmpChara.setValue('0.118');
tmpChara = tmpTool.AddCharacteristic('CL', '', 'Cutter Length', false);
tmpChara.setValue('0.748');
tmpChara = tmpTool.AddCharacteristic('R', '', 'Radius', false);
tmpChara.setValue('0.008');
tmpChara = tmpTool.AddCharacteristic('TA', '', 'Tip Angle', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('MD', '', 'Minimum Bore Diameter', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('CD', '', 'Connection Diameter', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('*B', '', 'Chip Breaker', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('*I', '', 'Tool Style', false);
tmpChara.setValue('');
tmpChara = tmpTool.AddCharacteristic('**', 'Shape Type_GRVR', 'Shape Type', false);
tmpChara.setValue('DOUBLE');
tmpTool.SpecialDescription = new SpecialDescription(GRVR.SpecialDescription.Delem, GRVR.SpecialDescription.List, GRVR.SpecialDescription.Label);
tmpTool.SpecialDescription.setValue('');
tmpTool.Manufacturer = new Manufacturer(GRVR.Manufacturer.Delem, GRVR.Manufacturer.List, GRVR.Manufacturer.Label);
tmpTool.Manufacturer.setValue('INGERSOLL');
tmpTool.ManufacturerNo = new ManufacturerNo(GRVR.ManufacturerNo.Delem, GRVR.ManufacturerNo.List, GRVR.ManufacturerNo.Label);
tmpTool.ManufacturerNo.setValue('TDC3 TT8020');
tmpTool.EDP = '6000200';
tmpTool.Availability = 'Available';
savTools.push(tmpTool);

That's a single object, and there's currently 800 and counting. This method runs reasonably quick, especially against using a For loop.

My method using a For loop was as follows (it crashed my browsers...):

var tmpTool;
var tmpChara;
tmpTool = new Tool();
tmpTool.Type = new Type(GRVR.Type.Delem, GRVR.Type.List, GRVR.Type.Case, GRVR.Type.Label, GRVR.Type.AlternateText);
tmpTool.ID = 1200;
for (var n = 0, len = CYL.Characteristics.length; n < len; n++){
    tmpChara = CYL.Characteristics[n];
    tmpChara = tmpTool.AddCharacteristic(tmpChara.Delem, tmpChara.List, tmpChara.Label, false);
    tmpChara.setValue(tmpVal[n]);
}
tmpTool.SpecialDescription = new SpecialDescription(GRVR.SpecialDescription.Delem, GRVR.SpecialDescription.List, GRVR.SpecialDescription.Label);
tmpTool.SpecialDescription.setValue('');
tmpTool.Manufacturer = new Manufacturer(GRVR.Manufacturer.Delem, GRVR.Manufacturer.List, GRVR.Manufacturer.Label);
tmpTool.Manufacturer.setValue('INGERSOLL');
tmpTool.ManufacturerNo = new ManufacturerNo(GRVR.ManufacturerNo.Delem, GRVR.ManufacturerNo.List, GRVR.ManufacturerNo.Label);
tmpTool.ManufacturerNo.setValue('TDC3 TT8020');
tmpTool.EDP = '6000200';
tmpTool.Availability = 'Available';
savTools.push(tmpTool);

The Questions

Should I be concerned about the length of my JS file, given my first example?

Should For Loops be avoided in an instance like this?

What are some other options for providing a page with JavaScript object data?

The Solution

I followed @Icepickle and @PatrickEvans suggestion to use JSON syntax to load the object data. Initially, I ran into the same issue that the (unchached) For Loops bogged down the browser. My solution was to simply convert the For Loops to chached loops (similar to the second example).

Upvotes: 0

Views: 296

Answers (2)

Icepickle
Icepickle

Reputation: 12796

If you would create your document as a JSON document containing the information that your javascript tool class implements, you could as PatrickEvans suggested, simply parse the data that comes from the server into your objects.

As an example, i made a smaller version of your model and parsed it (don't know from where your GRVR variable is coming, so i just added some dummy data)

An advantage of such a parsing model, is that you don't have to create lots of javascript files that manually prepare your Tools, but that you can supply the data to your class, and if your model would change in the future, it's lots easier to change the handling in one class, than in all your different (all be it generated) files.

var GRVR = {
    specialDescription: {
      dElem: 'dElem',
      list: 'list',
      label: 'label'
    },
    manufacturer: {
      dElem: 'dElem',
      list: 'list',
      label: 'label'
    },
    type: {
      dElem: 'dElem',
      list: 'list',
      label: 'label'
    }
  },
  documentFromServer = {
    characteristics: [{
      shortCut: '#M',
      description: 'Material Type',
      title: 'Material Type',
      hidden: false,
      value: ''
    }, {
      shortCut: '#G',
      description: 'Grade Type',
      title: 'Grade Type',
      hidden: false,
      value: ''
    }, {
      shortCut: 'FL',
      description: '',
      title: 'Functional Length',
      hidden: false,
      value: '0.79'
    }],
    edp: '6000200',
    availability: true,
    manufacturer: GRVR.manufacturer,
    specialDescription: GRVR.specialDescription,
    type: GRVR.type
  };


function Characteristic(properties) {
  var props = properties || {};
  this.shortCut = props.shortCut || '';
  this.description = props.description || '';
  this.title = props.title || '';
  this.hidden = !!props.hidden;
  this.value = props.value || null;

  this.setValue = function(val) {
    this.value = val || null;
  };
}

function DescriptiveElement(properties) {
  var props = properties || {};
  this.dElem = props.dElem || null;
  this.list = props.list || null;
  this.label = props.label || null;
}

function Tool(properties) {

  this._rawDocument = properties;
  this.characteristics = [];
  this.manufacturer = {};
  this.specialDescription = {};

  this.init = function() {
    var properties = this._rawDocument || {};
    this.setCharacteristics(properties.characteristics || []);
    this.specialDescription = new DescriptiveElement(properties.specialDescription);
    this.type = new DescriptiveElement(properties.type);
    this.manufacturer = new DescriptiveElement(properties.manufacturer);
    this.edp = properties.edp;
    this.availability = properties.availability;
  };

  this.setCharacteristics = function(cstics) {
    var i, len;
    this.characteristics = [];
    for (i = 0, len = cstics.length; i < len; i++) {
      this.characteristics.push(new Characteristic(cstics[i]));
    }
  };
  
  this.init();
}

var tmpTool = new Tool(documentFromServer);
console.log(tmpTool);

The size of your file can make a difference depending on the devices and the type of connections you need to support, although, in the current day and age, it should already be quite big to really make a difference. And if this would really matter, there is still possibility for minification of your javascript files...

You could check into making your website OData compatible by checking out the following tutorials.

Upvotes: 1

Jeff Lowery
Jeff Lowery

Reputation: 2597

I would question why you need to parse all that data in one go? How much of it can you actually display?

I would look into:

  1. paginating large arrays with range requests
  2. add a depth level parameter to allow you to drill down as needed in your view
  3. using a server-side template engine to generate the pages from the data before sending them to the browser

Upvotes: 0

Related Questions