titulusdesiderio
@titulusdesiderio
IT-специалист

Как реализовать многоуровневый вложенный запуск функций?

Боюсь что заголовок составлен в корне неверно не совсем понятно.


есть два класса объектов:
  • record — запись, содержащая в себе имя и значение.
    js и скрин из chrome devconsole
    var record = function() {
        var name;
        this.name = name;
        var value;
        this.value = value;
    }
    731ae871e917220e30c9de5aca4e6f6b.png
  • group — список, содержащий имя, статус и массив записей.
    js и скрин из chrome devconsole
    var group = function() {
        var _name;
        this.name = _name;
        var _status
        this.status = _status;
        var _stack = [];
        this.stack = _stack;
    }
    72029f916619519238c5c65c676d9dc2.png


Некоторые группы могут содержать в себе ещё группы, без ограничений на уровень вложенности.

Так же существует корневой элемент root — представляющий из себя группу нулевого уровня.


Нужно реализовать 2 функции:
  • makeRecord — создающая объект класса запись и помещающая его в стек текущего уровня вложенности.
    js
    var makeRecord = function(name,value) {
        var newrecord = new record();
        newrecord.name=name;
        newrecord.value=value;
        root.stack.push(newrecord);
    }

  • makeGroup — создающая объект класса группа, помещающая его в стек текущего уровня, и запускающая внутри себя переданную ей функцию, внутри которой могут находиться как новые вызовы makeRecord, так и makeGroup. Самое важное — она должна передавать им ссылку(?) на собственный stack
    js
    var makeGroup = function(name,fun) {
        var newgroup = new group();
        newgroup.name=name;
        var stack=[];
        try{fun();} catch(e) {
            newgroup.status=e;
        }
        newgroup.status='ok';
        newgroup.stack=stack;
        root.stack.push(newgroup);
    }



Вот с последним у меня как раз проблемы.

Из этого кода:
makeRecord('first record','some text');
makeGroup('first group');
makeRecord('second record','yet another text');
makeGroup('second group',function(){
    makeRecord('first record in second group','how can i do it?');
});


Текущая реализация даёт вот такой результат:
{
    "name": "root",
    "status": "ok",
    "stack": [
        {
            "name": "first record",
            "value": "some text"
        },
        {
            "name": "first group",
            "status": "ok",
            "stack": []
        },
        {
            "name": "second record",
            "value": "yet another text"
        },
        {
            "name": "first record in second group",
            "value": "how can i do it?"
        },
        {
            "name": "second group",
            "status": "ok",
            "stack": []
        }
    ]
}
скрин из chrome devconsole362a50d64635935dd854305e18dc7f4c.png


А хочу получить такой:
{
    "name": "root",
    "status": "ok",
    "stack": [
        {
            "name": "first record",
            "value": "some text"
        },
        {
            "name": "first group",
            "status": "ok",
            "stack": []
        },
        {
            "name": "second group",
            "status": "ok",
            "stack": [
                {
                    "name": "first record in second group",
                    "value": "how can i do it?"
                }
            ]
        }
    ]
}
скрин из chrome devconsolecddde3efaf6dc431ed1e3c9e609b8efe.png


Возможно всё это можно поправить буквально парой строк в makeGroup, а может я выбрал неверный подход в принципе. На всякий случай залил код из примеров сюда, что бы вам заново не набирать.
  • Вопрос задан
  • 3326 просмотров
Решения вопроса 1
@m-haritonov
Для этого, перед вызовом функции fun() в makeGroup значение root надо временно подменить на только что созданную группу. Вот новый код для makeGroup:
var makeGroup = function(name,fun) {
    var newgroup = new group();
    newgroup.name=name;
    newgroup.status='ok';
    newgroup.stack=[];
    
    var oldRoot = root;
    root = newgroup;
    
    try {
        fun();
    }
    catch(e) {
        newgroup.status=e;
    }
    
    root = oldRoot;
    
    root.stack.push(newgroup);
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
sheknitrtch
@sheknitrtch
Я вижу в исходниках строку:
root.stack.push(newrecord);

То есть функция makeRecord всегда добавляет новую запись в корень.
Я бы добавил ещё один аргумент parentGroup в

var makeRecord = function(name,value, parentGroup) {
    var newrecord = new record();
    newrecord.name=name;
    newrecord.value=value;
    if(parentGroup === undefined) {
        parentGroup = root;
    }
    parentGroup.stack.push(newrecord);
}

Аналогично подправить функцию makeGroup.
Пользоваться этими функциями можно будет так:

makeRecord('first record','some text');
makeGroup('first group');
makeRecord('second record','yet another text');
makeGroup('second group', function(parentGroup) {
    makeRecord('first record in second group','how can i do it?', parentGroup);
});


ИМХО, анализировать стек вызовов или заводить какие-то дополнительные глобальные переменные — это плохой вариант.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы