在JavaScript中使用异步回调调用递归函数
背景:我正在准备一些面试,复习一些计算机科学基础知识。我实现了几种用于遍历二进制排序树的算法,特别是顺序遍历,我能够使用同步函数以及Promission和async/await关键字很好地完成这项工作 对于一组额外的实践,我认为将其移植到异步回调函数将是一个有用的挑战,特别是因为我正在面试Node.js职位。但是我完全被它卡住了,虽然我最好还是继续学习其他的话题,但这次失败一直困扰着我,我一直在旋转我的轮子 因此,这是一个有趣的但挑战性的经典算法问题,而不是心脏微弱的问题!p> 数据因此,假设给你一个对象数组,每个对象代表一个节点。节点必须具有与数组中另一个节点的索引号相对应的在JavaScript中使用异步回调调用递归函数,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,背景:我正在准备一些面试,复习一些计算机科学基础知识。我实现了几种用于遍历二进制排序树的算法,特别是顺序遍历,我能够使用同步函数以及Promission和async/await关键字很好地完成这项工作 对于一组额外的实践,我认为将其移植到异步回调函数将是一个有用的挑战,特别是因为我正在面试Node.js职位。但是我完全被它卡住了,虽然我最好还是继续学习其他的话题,但这次失败一直困扰着我,我一直在旋转我的轮子 因此,这是一个有趣的但挑战性的经典算法问题,而不是心脏微弱的问题!p> 数据因此,假设给
值
、可选的左
和右
属性。比如说:
[
{"value":"root","left":1,"right":2},
{"value":"L1","right":3},
{"value":"R1"},
{"value":"R2"}
]
如果将其绘制为二叉树,它看起来像:
root
/ \
/ \
L1 R1
\
\
R2
并实现顺序遍历,值应显示为'L1,R2,root,R1'
在同步解决方案中,我编写了两个helper方法来获取根节点(假设数组的第一个元素始终是根)和另一个方法来查找特定索引处的节点。解决方案如下:
function SyncTree(data) {
this.data = data;
};
SyncTree.prototype.getRoot = function () {
return this.data[0];
};
SyncTree.prototype.getNode = function (index) {
return this.data[index];
};
SyncTree.prototype.orderTree = function () {
const results = [];
const inorder = node => {
if (node) {
inorder(this.getNode(node.left));
results.push(node.value);
inorder(this.getNode(node.right));
}
}
inorder(this.getRoot());
return results;
}
对于基于承诺的解决方案,我让我的助手函数返回一个承诺对象,而不仅仅是值,而且我能够非常轻松地处理它,因为async/await使代码看起来是同步的
function PromiseTree(data) {
if (!Array.isArray(data)) {
throw new Error('The data must be an Array');
}
this.data = data;
};
PromiseTree.prototype.getRoot = function (callback) {
return Promise.resolve(this.data[0]);
};
PromiseTree.prototype.getNode = function (index, callback) {
return Promise.resolve(this.data[index]);
};
PromiseTree.prototype.orderTree = function () {
const results = [];
const inorder = async node => {
if (node) {
const left = await this.getNode(node.left);
await inorder(left);
results.push(node.value);
const right = await this.getNode(node.right);
await inorder(right);
}
}
return this.getRoot().then(async root => {
await inorder(root);
return Promise.resolve(results);
});
}
对于回调挑战,我编写了一些简单的逻辑,使其立即返回值或随机延迟。我知道在现实世界中,在这个用例中使用回调函数绝对是迟钝的,而同步方法将是首选,但我的头撞到了墙上,我被卡住了。到目前为止,这就是我得到的结果,但它返回的结果不一致,因为某些回调函数在其他回调函数之前启动
function CallbackTree(data) {
if (!Array.isArray(data)) {
throw new Error('The data must be an Array');
}
this.data = data;
};
function inconsistentCallback(value, callback) {
if (Math.random() > 0.5) {
setImmediate(function () {
callback(null, value);
});
} else {
callback(null, value);
}
}
CallbackTree.prototype.getRoot = function (callback) {
inconsistentCallback(this.data[0], callback);
};
CallbackTree.prototype.getNode = function (index, callback) {
inconsistentCallback(this.data[index], callback);
};
CallbackTree.prototype.orderTree = function (callback) {
const results = [];
const inorder = (node, cb) => {
if (node) {
results.push(node.value)
this.getNode(node.left, (err, left) => {
this.getNode(node.right, (err, right) => {
inorder(node.left, cb)
inorder(node.right, cb)
cb()
})
})
}
}
this.getRoot((err, root) => {
inorder(root, () => {
if (results.length === this.data.length) {
callback(null, results)
}
});
});
}