2015-06-18 1 views
0

Моей Нокаут модели (версия 3.3.0 от нокаута) что-то вроде этого:Избегайте ошибки циклического значения ввиду, Нокаут

var Node= function(id,name,parentNode) { 
      var self = this; 
      self.id= ko.observable(id); 
      //more here... 
      self.nodes = ko.observableArray([]); 
      self.parentNode = parentNode; 
     } 

Когда эта модель связана с тем, Нокаут выдает ошибку в консоль (неразрывный ошибка):

TypeError: cyclic object value

...m http://www.json.org/json2.js ");return E.stringify(a.a.c(b),c,g)},zc:function(c...

knockout-3.3.0.js (line 20, col 344)

Таким образом, я предполагаю, что где-то внутри, нокаут вызывает метод JSON.stringify. Объединив ответы от here и here, я пришел к выводу, что если я добавлю метод «toJSON» в свою модель, где я исключил свойство «parentNode», ошибка исчезнет. И так оно и есть.

Моего toJSON функция:

self.toJSON = function(){ 
        return { 
         id: self.id(), 
         name: self.name(), 
         //exclude parentNode 
         nodes: ko.toJSON(self.nodes()) 
        }; 
       } 

Так что мой вопрос: есть ли более эффективный способ, чтобы написать эту функцию, чтобы быть более универсальными? Я хочу включить все (неизвестные) свойства, за исключением нескольких (известных).

Вызов ko.toJSON на модели, а затем удаление объекта, поскольку первая ссылка предполагает, что это не сработает из-за циклической ссылки. Итак, любые другие альтернативы?

EDIT: Подразумеваемый звонок toJSON при привязке осуществляется другим плагином ko, но это действительно может быть что угодно. Я установка изолированной скрипку, чтобы продемонстрировать как проблему, и мое временное решение здесь: http://jsfiddle.net/zq09znLa/1/

+0

проверка рабочего образца здесь http://jsfiddle.net/LkqTU/24754/. дайте мне знать приветствия –

+0

@supercool Извините, но ваш ответ не связан с моей проблемой. См. Мое редактирование, я добавил воспроизводимую скрипку. – pkExec

+0

Зарегистрируйте узлы в словаре по id, а затем храните узлы в виде массива идентификаторов, с вычисленными для генерации фактического списка узлов. Аналогичным образом сохраните идентификатор родительского узла и вычислите (если хотите), чтобы получить сам узел. –

ответ

1

Вы можете использовать функцию заменителя (см solution here), чтобы исключить нежелательные клавиши:

var excludeKeys = { 
    parentNode: true 
}; 

Это немного неудобно , так как вы должны временно удалить self.toJSON, чтобы избежать бесконечной рекурсии.

self.toJSON = function() { 
    var save = self.toJSON; 
    delete self.toJSON; 
    var result = ko.toJSON(self, function (key, value) { 
     if (key in excludeKeys) return null; 
     return value; 
    }); 
    self.toJSON = save; 
    return result; 
}; 

Я обновил свою скрипку, так что работает в Chrome и демонстрирует решение: http://jsfiddle.net/zq09znLa/4/

Update: Я сделал версию с toJSON определяется как пустая функция в прототипе. Это заставляет программу работать успешно (с точки зрения ожидаемого вывода), просто сводя на нет сериализацию.

Node.prototype = { 
    toJSON: function() {} 
}; 

Я хотел сделать прототип, проживающий toJSON, который работает, но скрипка не испытывать делают ли toJSON правильных вещей.

http://jsfiddle.net/2o7cnzL2/1/

+0

Эта часть с временным удалением «toJSON» была блестящей. Благодаря! – pkExec

+0

@pkExec JSFiddle's TidyUp испортил HTML, так что это исправлено. Кроме того, новое решение использует прототип вместо локального 'toJSON' –

+0

Нет, ваше последнее редактирование в скрипте, которая сводит на нет сериализацию, не является тем, что было задано. Лучше сохранить его по-прежнему (за вычетом ошибок HTML) для будущих читателей. – pkExec

Смежные вопросы