Вызов рекурсивного метода Meteor вызывает бесконечный цикл

Учитывая (родительский) узел в дереве, мне нужно получить [1] Количество дочерних элементов под родительским плюсом под дочерними элементами родительского плюс дочерние дочерние элементы родителя и т. д. [2] Количество дочерних элементов из [1], которые помечены как «ОТКРЫТЫЕ» .

У моих тестовых данных есть один родитель, у которого есть два ребенка. Мой метод -

Meteor.methods({
...
   'getSubCounts': function(selectedNodeId){
    var children = ItemList.find({"parent.parentid": selectedNodeId}).fetch();
    var numChildren = children.length;
    console.log("Number of children of " + selectedNodeId + ": " + numChildren);

    var openChildrenCount = children.filter(function(row) {
        return (row.status === "OPEN");
    }).length;

    for (i = 0; i < numChildren; i++) { 
        console.log("iterations for child " + i + ": " + children[i]._id);

        Meteor.call('getSubCounts', children[i]._id, function(error, result) {
            if(error) {
                console.log("error occured during iteration " + error);
            } else {
                numChildren = numChildren + result.numChildren;
                openChildrenCount = openChildrenCount + result.openChildrenCount;
            }
        });

    }

    return {numChildren: numChildren, openChildrenCount: openChildrenCount};
    },
...
});

Который я вызываю в помощнике на стороне клиента -

'subcounts': function(){
    if (this._id != null) {
        Meteor.call('getSubCounts', this._id, function(error, result) {
            if(error) {
                // nothing
            } else {
                Session.set('subcountsdata', result)
            }
        });

Из вывода (браузера) кажется, что он повторяется, как и ожидалось, для первого дочернего элемента, но второй застрял в бесконечном цикле. (Обратите внимание, что идентификатор родительского узла — 8veHSdhXKjyFqYZtx, а идентификаторы дочерних узлов — iNXvZGaTK3RR6Pekj,C6WGaahHrPiWP7zGe)

Number of children of 8veHSdhXKjyFqYZtx: 2
iterations for child 0: iNXvZGaTK3RR6Pekj
Number of children of iNXvZGaTK3RR6Pekj: 0
iterations for child 1: C6WGaahHrPiWP7zGe 
Number of children of C6WGaahHrPiWP7zGe: 0 
iterations for child 1: C6WGaahHrPiWP7zGe
Number of children of C6WGaahHrPiWP7zGe: 0 
iterations for child 1: C6WGaahHrPiWP7zGe
Number of children of C6WGaahHrPiWP7zGe: 0 
iterations for child 1: C6WGaahHrPiWP7zGe
Number of children of C6WGaahHrPiWP7zGe: 0 
....

Почему в этом случае вторая итерация происходит бесконечно? Похоже, это связано с реактивностью, но я не могу понять настоящую причину.


person Jay    schedule 18.01.2019    source источник


Ответы (1)


Очень вероятно, что вам просто не хватает var i в вашей функции метода.

Без объявления i в качестве локальной переменной вы используете глобальную переменную области видимости, которой присваивается значение 0 каждый раз, когда вы вызываете свой метод.

КСТАТИ:

  • избегайте повторяющихся методов Meteor. Вы создаете цикл сетевых запросов. Если вам нужна рекурсия, используйте специальную функцию.
  • избегайте вызова методов Meteor в помощниках. Вместо этого используйте ReactiveVar и выполняйте вызов только при необходимости, как правило, в обработчике жизненного цикла шаблона Blaze (например, onCreated) или в прослушивателе событий.
person ghybs    schedule 18.01.2019
comment
Вы на месте! И спасибо, это хорошие моменты. На данный момент я переместил вызов клиентского метода в onCreated(), а не в помощник. - person Jay; 19.01.2019
comment
Просто любопытно, есть ли потенциально лучший способ получить данные дерева без рекурсии? - person Jay; 19.01.2019
comment
Вероятно, не в простой иерархической древовидной структуре данных. - person ghybs; 19.01.2019