Как создать обратный вызов, когда ансинхронный рекурсивный метод полностью готов? - PullRequest
0 голосов
/ 19 декабря 2011

Мне нужно, чтобы рекурсивная функция выполнялась асинхронно, с обратным вызовом, который происходит после того, как ревизия полностью завершена.Я упростил его, чтобы избавиться от не относящихся к делу частей (вот код в jsfiddle: http://jsfiddle.net/DgaBg/8/)

tree = {
    "a": {
        "b": 1,
        "c": 2
    },
    "d": {
        "e": {
            "f": {
                "g": 3
            },
            "h": 4,
            "i": 5
        },
        "j": {
            "k": 6,
            "l": 7
        },
        "m": 8,
        "n": 9
    },
    "o": {
        "p": 10
    },
    "q": 11
};

Watcher = function() { };

Watcher.prototype.startDoingAsyncStuff = function(node, callback) {
    var me = this,
        key;

    if(typeof node === "number") {
        console.log(node);
    } else {
        for(key in node) {
            if(node.hasOwnProperty(key)) {
                (function(node) {
                    setTimeout(function() {
                        me.startDoingAsyncStuff(node, callback);
                    }, 500);
                }(node[key]));
            }
        }
    }
};

w = new Watcher();

w.startDoingAsyncStuff(tree, function() {
    console.log("callback 1");
});

w.startDoingAsyncStuff(tree["d"], function() {
    console.log("callback 2");
});

Мне нужен обратный вызов, предоставленный Watcher.startDoingAsyncStuff для выполнения после завершения отказов, но яЯ не уверен, как этого добиться.

Сложный фактор заключается в том, что использование простого счетчика невозможно, поскольку Watcher.startDoingAsyncStuff может быть выполнен несколько раз, не дожидаясь завершения предыдущих вызовов.

Любая помощь по этому вопросу будет принята с благодарностью.

Ответы [ 2 ]

2 голосов
/ 19 декабря 2011

По сути, для суб-вещи, вы хотите предоставить обратный вызов, который просто уведомляет уровень над ним, что это сделано.На более высоком уровне у вас есть количество «готовых» сообщений, которые вы ожидаете получить, и как только вы получите этот номер, вы вызываете «реальный» обратный вызов.

Первоначально у меня был прототип счетчика, который будет делатьэто за пределами функции, но фактическая функциональность настолько проста, что я включил ее в саму функцию.

Watcher.prototype.startDoingAsyncStuff = function(node, callback) {
    var me = this,
        key,
        jobCount = 0;

    if (typeof node === "number") {
        console.log(node);
        // There's no sub-stuff to do, so we're done here
        callback();
    } else {
        for (key in node) {
            if (node.hasOwnProperty(key)) {
                (function(node) {
                    ++jobCount;
                    setTimeout(function() {
                        // we create a sub-callback to decrement the counter
                        // and run the "real" callback when the counter is back
                        // to 0.
                        // This works as many times as needed, because jobCount
                        // is local and accessed via closure.
                        me.startDoingAsyncStuff(node, function() {
                            if (--jobCount == 0) callback();
                        });
                    }, 500);
                }(node[key]));
            }
        }
    }
};
0 голосов
/ 19 декабря 2011

Без добавления дополнительных тайм-аутов одним из способов было бы сделать первый проход дерева, фактически не выполняя ни одной из основных задач, а вместо этого посчитав количество воскресений.Предполагая, что ваше дерево не массивно, вы должны делать это синхронно, не блокируя браузер.

Затем выполните второй проход, и после выполнения каждой основной асинхронной задачи увеличьте значение другого счетчика;когда он соответствует счету с первого прохода, вы можете запустить обратный вызов.

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