knockout.mapping
knockout.mapping copied to clipboard
async version of ko.mapping.fromJS to prevent script timeout errors
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?
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).
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);
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);
}