如何在异步递归方法完全就绪时创建回调

How to create a callback when an ansynchronous recursive method is completely ready

本文关键字:就绪 创建 回调 异步 递归方法      更新时间:2023-09-26

我需要一个递归函数与一个在递归完全完成后发生的回调异步发生。我简化了它,去掉了不相关的部分(这里是jsfiddle中的代码。

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应该能够在不等待先前调用完成的情况下执行多次。

基本上,对于子材料,你想要提供一个回调,它只是通知它上面的级别它已经完成了。在更高的级别,你有一个"完成"消息的计数,你期望接收,一旦你得到这个数字,你调用"真实"回调。

我最初有一个计数器原型,它可以在函数之外完成此操作,但实际功能非常简单,因此我将其合并到函数本身中。

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

在不添加额外超时的情况下,一种方法是在不实际执行任何主要任务的情况下对树进行第一次遍历,而是计算遍历的次数。假设你的树不是很大,你应该能够在不锁定浏览器的情况下同步完成这个操作。

然后执行第二次传递,并在执行每个主异步任务后增加另一个计数器;当它匹配第一次传递的计数时,您可以触发回调。