Как использовать обещания для возврата массива объектов, которые рекурсивно редактируются в экспресс-маршрутизаторе в nodejs?

Я пытаюсь вернуть массив объектов узла, каждый из которых имеет уникальную метку и массив дочерних узлов, каждый из которых идентифицируется своей уникальной меткой, для использования в моем интерфейсе с компонентом дерева (https://reactjsexample.com/a-simple-react-tree-menu-component/). Категория — это список mongodb с родительской меткой, дочерним массивом дочерних меток, собственной уникальной меткой и номером.

Выполнение функции createTreeJson без промиса и печать treeData после задержки выводит правильный результат. Я попытался преобразовать recursiveCat, чтобы вернуть обещание и поставить .then после каждого вызова recursiveCat:

recursiveCat(node.nodes, category.label, indexC).then(() => resolve()); 

но это так и не закончило вызов API. Я очень новичок в обещаниях, и они меня сбивают с толку, несмотря на некоторые исследования.

router.get("/tree", (req, res) => {
var treeData= [];
createTreeJson(treeData).then(() => res.json(treeData));
function createTreeJson(treeData){
    return new Promise(resolve => {
        Category.find({ level: 0 }).then( categories => {
            categories.forEach((category) => {
              var node = {
                key: category.label,
                label: category.label,
                index: treeData.length,
                nodes: []
              }
              treeData.push(node);
              recursiveCat(node.nodes, category.label, treeData.length);
              resolve();
            });
          });
    })
}
function recursiveCat(nodes, parLabel, indexC){
  console.info("cat call")
    Category.find({ parent: parLabel }).then( categories => {
      categories.forEach((category) => {
        //console.info(category.children.length)
        var node = {
          key: category.label,
          label: category.label,
          index: indexC,
          nodes:  []
        }
        nodes.push(node);
        recursiveCat(node.nodes, category.label, indexC);
      })
    })
  }
})

Результат:

[
    {
        "key": "Video Games",
        "label": "Video Games",
        "index": 0,
        "nodes": []
    },
    {
        "key": "Sports",
        "label": "Sports",
        "index": 1,
        "nodes": []
    }
]

Ожидается (генерируется из того же кода, но без промисов и печатается с задержкой, а в качестве примера показаны только виды спорта):

{ key: 'Sports',
  label: 'Sports',
  index: 1,
  nodes:
   [ { key: 'Basketball', label: 'Basketball', index: 2, nodes: [] },
     { key: 'Combat Sports',
       label: 'Combat Sports',
       index: 2,
       nodes: [] },
     { key: 'Soccer', label: 'Soccer', index: 2, nodes: [] },
     { key: 'Tennis', label: 'Tennis', index: 2, nodes: [] },
     { key: 'Track', label: 'Track', index: 2, nodes: [] },
     { key: 'Volleyball', label: 'Volleyball', index: 2, nodes: [] },
     { key: 'Football', label: 'Football', index: 2, nodes: [] },
     { key: 'Hockey', label: 'Hockey', index: 2, nodes: [] },
     { key: 'Golf', label: 'Golf', index: 2, nodes: [] },
     { key: 'Rugby', label: 'Rugby', index: 2, nodes: [] } ] }

Любая помощь приветствуется, спасибо! Это первый вопрос, который я задал, поэтому, если я задал неправильно или у меня нет информации, дайте мне знать!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
39
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В вашем коде 2 проблемы:

  • resolve() похож на return, вам нужно что-то вставить. Вы должны написать:

    resolve(recursiveCat(node.nodes, category.label, treeData.length))

  • Ваша рекурсивная функция ничего не возвращает. Я думаю, что это должно выглядеть примерно так:

function recursiveCat(nodes, parLabel, indexC){
  console.info("cat call");
    Category.find({ parent: parLabel }).then( categories => {
      categories.forEach((category) => {
        var self_node = recursiveCat(node.nodes, category.label, indexC);
        var node = {
          key: category.label,
          label: category.label,
          index: indexC,
          nodes:  self_node
        }
        nodes.push(node);
        
        
      });
      return nodes;
    });
  }

Спасибо за ответ. У меня это работает с решением pindev, но я заставлю и ваше работать, просто чтобы лучше понять, как оно работает.

Jensen Rice 03.06.2019 05:37
Ответ принят как подходящий

Попробуйте следующий код, пожалуйста.

var treeData= [];
createTreeJson(treeData).then((r) => res.json(r));
function createTreeJson(treeData){
    return Category.find({ level: 0 }).then( categories => {
        return Promise.all(
            categories.map(category => {
                var catArray = {
                    key: category.label,
                    label: category.label,
                    index: treeData.length,
                    nodes: []
                };
                return recursiveCat(node.nodes, category.label, treeData.length).then(
                    r => (catArray.nodes = r, catArray)
                );
            }
        ));
    });
}

function recursiveCat(nodes, parLabel, indexC){
    return Category.find({ parent: parLabel }).then( categories => {
        return Promise.all(categories.map((category) => {
            var catArray = {
                key: category.label,
                label: category.label,
                index: indexC,
                nodes:  []
            };
            return recursiveCat(node.nodes, category.label, indexC).then(
                r => (catArray.nodes = r, catArray)
            );
        }));
    })
}

Спасибо! Это сработало. Мне нужно изучить Promise.all и .map.

Jensen Rice 03.06.2019 04:54

Другие вопросы по теме