javascript 如何使用递归API调用构建对象树?

z9smfwbn  于 2022-11-20  发布在  Java
关注(0)|答案(1)|浏览(197)

我想构造一个树,其中每个节点都在API调用中使用以获取子节点;从根目录开始。这将递归执行,直到到达TREE_DEPTH_LIMIT

  1. export const search = async (searchTerm) => {
  2. try {
  3. const tree = {};
  4. await createTree(searchTerm, tree);
  5. return tree;
  6. } catch (err: any) {}
  7. };
  8. const TREE_DEPTH_LIMIT = 3;
  9. const createTree = async (searchTerm, tree) => {
  10. if (counter === TREE_DEPTH_LIMIT) {
  11. counter = 0;
  12. return;
  13. }
  14. counter++;
  15. tree[searchTerm] = {};
  16. try {
  17. const res = await axiosInstance.get(
  18. `/query?term=${searchTerm}`
  19. );
  20. // res.data.terms is an array of strings
  21. res.data.terms.forEach((term) => {
  22. createTree(term, tree[searchTerm]);
  23. });
  24. } catch (err) {}
  25. };

我尝试在上面的createTree()函数中递归地执行此操作。它将在API调用中使用searchTerm。然后它将遍历res.data.terms并在每个条件上调用createTree()。但输出不是我所期望的。
输出如下:

  1. const tree = {
  2. apple: {
  3. apple_tree: {},
  4. tree: {},
  5. },
  6. };

预期输出:(因为TREE_DEPTH_LIMIT为3,所以树中应有3个级别)

  1. const tree = {
  2. apple: {
  3. apple_tree: {
  4. leaf: {},
  5. },
  6. tree: {
  7. trunk: {},
  8. },
  9. },
  10. };

还是我的解决方案完全不正确,我应该去另一种方法?

wfauudbj

wfauudbj1#

一些问题:

  • counter看起来是一个全局变量,但这样做效果不好,因为每次递归返回时,counter都应该恢复它的值。最好使用一个局部变量,这样每个执行上下文都有它自己的版本。更好的方法是将它作为一个参数,让它向下计数而不是向上计数。
  • 递归调用是不等待的,因此在search中,createTree返回的promise可能在所有子节点都被填充之前就解决了,因此您将使用一个不完整的树。
  • 这不是一个真实的的问题,但调用者必须创建一个tree对象并将其作为参数传递,这并不是最优雅的。我将重新设计函数,以便search将自己创建该对象,然后使用递归函数创建 children --因此我将该函数命名为createChildren,而不是createTree

下面是一个代码片段,它首先模拟get方法,以便您可以实际运行它:

  1. // Mock for this demo
  2. const axiosInstance = {async get(term) {const delay = ms => new Promise(resolve => setTimeout(resolve, ms));await delay(50);return {data: {terms: {"apple": ["apple_tree", "tree"],"apple_tree": ["leaf"],"leaf": [],"tree": ["trunk"],"trunk": []}[term.split("=")[1]]}};}}
  3. const createChildren = async (searchTerm, depth) => {
  4. if (depth-- <= 0) return {};
  5. try {
  6. const res = await axiosInstance.get(`/query?term=${searchTerm}`);
  7. const promises = res.data.terms.map(async (term) =>
  8. [term, await createChildren(term, depth)]
  9. );
  10. return Object.fromEntries(await Promise.all(promises));
  11. } catch (err) {
  12. console.log(err);
  13. }
  14. };
  15. const TREE_DEPTH_LIMIT = 3;
  16. const search = async (searchTerm, depth=TREE_DEPTH_LIMIT) =>
  17. ({[searchTerm]: await createChildren(searchTerm, depth)});
  18. // Demo
  19. search("apple").then(tree =>
  20. console.log(tree)
  21. );
展开查看全部

相关问题