2013-03-04 22 views
6

Alcuni dei nostri utenti sono ancora su IE8. Alcuni di loro occasionalmente segnalano problemi quando provano a inviare dati ai nostri server (tramite un grosso pulsante con l'etichetta "SAVE").KnockoutJS con IE8, problemi occasionali con Stringify?

C'è un errore di script che IE8 mostra, che è: chiamata imprevista di metodo o proprietà di accesso, sempre indicando la stessa linea nei KnockoutJS 2.2.0 (debug, per ora) biblioteca, la linea 450, che è il seguente:

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

procedimento nel mio codice che è alla base della stack quando ciò accade è questo:

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" 
     }); 
    }; 

Noi spogliare una serie di proprietà che non sono necessarie al nostro post come convertiamo il opporsi a JSON, utilizzando questo approccio: 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; 
} 

Quando fallisce, fallisce costantemente sulla linea

var jsonData = ko.toJSON(self); 

Ora arriva il vero disastro:

  1. Non è costantemente accadendo
  2. Non capita a tutti gli utenti di IE8
  3. Non possiamo costantemente riprodurlo
  4. La struttura del nostro modello che stiamo serializzazione non sembra importa
  5. Il jscript.dll è la versione corrente per IE8

risposta

1

ho idea se questo sarà risolvere il problema, ma è possibile utilizzare il mapping plugin di andare tra i JS e JSON:

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

preso dalla mia answer to this question

Farei una prova e vedere se è d'aiuto, perché non c'è niente di sbagliato nel tuo approccio.

0

Sei sicuro che siano gli utenti IE8 che stanno riscontrando il problema? IE7 does not support JSON.stringify. Dovrai includere lo json2.js library per supportare IE7 e inferiore.

+0

Includiamo json2 per gli utenti di IE7. Nessun utente IE7 ha segnalato un problema; solo gli utenti IE8. – reallyJim

+0

Interessante. Potrebbe essere che gli utenti di IE8 siano effettivamente in esecuzione in modalità di emulazione IE7 (compatibilità di pagine IE)? –

+0

Il nostro staff addetto al controllo qualità è * a volte * in grado di riprodurlo ed è in modalità IE8 quando lo fa. – reallyJim

2

Ho riscontrato anche questo problema. Scavando più a fondo ho trovato un paio di cose:

  • E 'stato solo venendo a mancare di tanto in tanto, ho trovato questo eseguendo il codice nella console enter image description here
  • Il codice nel data-bind stato trowing un'eccezione se non il messaggio che veniva inghiottito a causa di IE8 inghiottire il messaggio quando si utilizza un blocco try {} finally {} (senza catch).
  • La rimozione della prova ha rivelato infine che un messaggio di associazione non può essere analizzato.

Quando ho iniziato ad avvicinarmi a capire il problema (scavando in profondità nel codice ad eliminazione diretta) sembrava scomparire di fronte ai miei occhi. Questa è la sezione di codice che stava fallendo in poi, cattura l'eccezione alla fine del codice:

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's 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's 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); 
     } 
    } 
}); 

Ma sì, si è fermato diventando riproducibile così mi si avvicinò con un hack che ho testato e funziona in precedenza, solo riprovare l'analisi dei dati. Quindi questo:

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

E'questo:

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

Sì, è molto schifo, ma sembra fare il trucco fino a quando i nostri utenti non hanno più bisogno IE8 o la questione Knockout è fisso.

+0

Ok, questo è schifo. :) Lo abbiamo superato ora, avendo invece creato i nostri metodi toJSON direttamente nei nostri oggetti. Il lato negativo è che è sbagliato implementare nuovamente qualcosa che avrebbe dovuto funzionare, ma dal momento che ora creiamo il nostro, non devo più fare il passo dell'eliminazione delle proprietà di cui non mi importa. Spada a doppio taglio, immagino. – reallyJim