KnockoutJS with IE8, random problems with Stringify?

A number of our users are still on IE8. Some of them sometimes report problems when trying to send data to our servers (using the large button that says "SAVE").

IE8 displays a script error, which is: An unexpected method call or access to properties, always pointing to the same line in the KnockoutJS 2.2.0 library (debug, for now), line 450, which is as follows:

return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space); 

The method in my code that is in the root trace line of the stack where this happens is:

 self.saveSingle = function (onSuccess, onFailure) { ko.utils.arrayForEach(self.days(), function (day) { day.close(); }); var jsonData = ko.toJSON(self); $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: applicationLocation + "/api/assignmentapi/save", data: jsonData, success: function (data) { self.status(data.Status); self._isDirty(false); ko.utils.arrayForEach(self.days(), function (day) { day.clean(); }); if (onSuccess) onSuccess(); }, error: function (data) { onFailure(); }, dataType: "json" }); }; 

We highlight a number of properties that our POST does not need when we convert the object to JSON using this approach: http://www.knockmeout.net/2011/04/controlling-how-object-is-converted-to.html

 OurType.prototype.toJSON = function () { var copy = ko.toJS(this); delete copy.someUnneededProperty1; delete copy.someUnneededProperty2; delete copy.someUnneededProperty3; delete copy.someUnneededProperty4; return copy; } 

When he fails, he does not consistently work on the line

 var jsonData = ko.toJSON(self); 

Now here is the real mess:

  • This does not always happen.
  • This does not happen with all IE8 users.
  • We cannot play it sequentially
  • The structure of our model, which we serialize, does not look material.
  • jscript.dll is the current version for IE8
+6
source share
3 answers

I also experienced this problem. Digging deeper, I discovered several things:

  • It was just unsuccessful, I found this by running the code in the console enter image description here
  • The code in data-bind threw an exception, except that the message was swallowed because IE8 was collecting the message when using the try {} finally {} catch (without catch ).
  • Removing the attempt finally showed that the parsing message could not be completed.

When I began to approach the problem clarification (digging deep into the knockout code), it seemed to disappear before my eyes. This is the section of code in which it did not fire, catching the exception at the end of the code:

 ko.utils.extend(ko.bindingProvider.prototype, { 'nodeHasBindings': function(node) { switch (node.nodeType) { case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node default: return false; } }, 'getBindings': function(node, bindingContext) { var bindingsString = this['getBindingsString'](node, bindingContext); return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null; }, // The following function is only used internally by this default provider. // It not part of the interface definition for a general binding provider. 'getBindingsString': function(node, bindingContext) { switch (node.nodeType) { case 1: return node.getAttribute(defaultBindingAttributeName); // Element case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node default: return null; } }, // The following function is only used internally by this default provider. // It not part of the interface definition for a general binding provider. 'parseBindingsString': function(bindingsString, bindingContext, node) { try { var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache); return bindingFunction(bindingContext, node); } catch (ex) { throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString); } } }); 

But yes, it stopped being reproducible, so I came up with a hack that I tested and works before, just repeat the parsing of the data. So:

 data-bind="value: ko.computed(function(){return ko.toJSON(appViewModel.model()[0])})" 

It became as follows:

 data-bind="value: ko.computed(function(){while (true) { try { var json = ko.toJSON(appViewModel.model()[0]); return json; }catch(e){}}})" 

Yes, this is very yucky, but it seems to be a trick until our users no longer need IE8 or the knockout problem is fixed.

+2
source

I don't know if this will be fixed, but you can use the mapping plugin to transition between JS and JSON:

 var mapping = { 'ignore': ["propertyToIgnore", "alsoIgnoreThis"] } var viewModel = ko.mapping.toJS(data, mapping); 

Taken from my answer to this question

I would try and see if this helps, since there is nothing obviously wrong with your approach.

+1
source

Are you sure IE8 users are facing a problem? IE7 does not support JSON.stringify . You will need to enable json2.js library to support IE7 and below.

0
source

All Articles