knockout.mapping icon indicating copy to clipboard operation
knockout.mapping copied to clipboard

async version of ko.mapping.fromJS to prevent script timeout errors

Open fbuchinger opened this issue 12 years ago • 3 comments

Hi, I have a fairly complex, deeply hierarchical JSON model that gets converted to a knockout model structure using ko.mapping.fromJS. Unfortunately, I'm getting the "script is running slowly" (http://support.microsoft.com/kb/175500/en-us) error dialog in IE8. One way to circumvent this is to use an async approach, since the statement counter is resetted for aynchronously invoked functions (http://stackoverflow.com/questions/4460263/disabling-the-long-running-script-message-in-internet-explorer). How can I achieve this with knockout.mapping?

fbuchinger avatar Feb 19 '13 18:02 fbuchinger

The only way to do that currently is by splitting up your model into parts and doing mapping of those parts individually (i.e. multiple ko.mapping.fromJS statements, each in a separate timeout).

sagacity avatar Feb 20 '13 09:02 sagacity

Unfortunately this is not so easy for me. I already use multiple 'ko.mapping.fromJS' calls in my model hierarchy to create child objects (i.e. the form model as root model generates group models, these generate field models). I also use a lot of context dependent mapping options (i.e. generate sub-model objects instead of observables) and have no idea how I can accomplish that in "async" mode. Are there any jsfiddles/code samples?

FYI here is a simplified version of my JSON structure:

var formData = {
    name: 'MainForm',
    groups: [{
        name: 'Group1',
        visible: true,
        editable: true,
        fields: [{
            name: 'Group1Field1',
            visible: true,
            editable: true
        }, {
            name: 'Group1Field2',
            visible: true,
            editable: true
        }, ]
    }, {
        name: 'Group2',
        fields: [{
            name: 'Group2Field1',
            visible: true,
            editable: true
        }, {
            name: 'Group2Field2',
            visible: true,
            editable: true
        }, ]
    }]
}

my model code goes like this:


function FormModel (jsonData){
  this.name = jsonData.name;
  var mapping = {
     'groups': {
         create: function (data){
             return new GroupModel(data);
         }
     }
  }
  ko.mapping.fromJS(jsonData, mapping, this);
}

function GroupModel (jsonData){
  this.name = jsonData.name;
  var mapping = {
     'fields': {
         create: function (data){
             return new FieldModel(data);
         }
     }
  }
  ko.mapping.fromJS(jsonData, mapping, this);
}

function FieldModel (jsonData){
  this.name = jsonData.name;
  ko.mapping.fromJS(jsonData, {}, this);
}

var form = new FormModel(formData);


fbuchinger avatar Feb 21 '13 11:02 fbuchinger

Is it hitting on the timeout for mapping a single model, or do you have an operation that maps multiple models that fails?

If it's the second and it's being done in a loop, what worked for us to get around the timeout was to move from:

for (data in array) {
  var model = new Model(data);
  // Do something with model
}

to:

for (data in array) {
  // Make the call to do something async
  window.setTimeout(function() {
    var model = new Model(data);
    // Do something with model
  }, 1);
}

timtucker avatar Mar 22 '13 11:03 timtucker