Обещание не возвращается из рекурсивной функции - PullRequest
3 голосов
/ 19 апреля 2020

Фон

У меня проблема с тем, что мое обещание не возвращается к вызывающей функции. Я знаю, что это обычно работает, но не в рекурсивной функции. Вызывается разрешение, и я вижу, что функция FindElementById правильно находит элемент, однако вызов в значении UpdateMasterMenuItem(result, queuedItem) не вызывается.

Что я делаю в своих фрагментах кода, что я пытаюсь сделать?

L oop над коллекцией queuedItems и найти эти элементы в другой коллекции menuItems. Я делаю это, передавая идентификатор элемента, который я пытаюсь найти, а также коллекцию, в которой он находится, в рекурсивную функцию FindElementById. Когда предмет найден, я возвращаю найденный предмет и выполняю другие операции с ним в функции UpdateMasterMenuItem.

Код

// Calling Loop
        queuedItems.forEach(function (queuedItem) {
            FindElementById(queuedItem.dataset.id, menuItems).then(function(result) {
                UpdateMasterMenuItem(result, queuedItem);
            });
        });


// Recursive Function
function FindElementById(id, menuItems) {
    return new Promise((resolve) => {
        menuItems.forEach(function (menuItem) {
            if (menuItem.Id === id) {
                return resolve(menuItem);

            } else if (menuItem.Child.length > 0) {
                FindElementById(id, menuItem.Child);
            }
        });
    });
}

1 Ответ

2 голосов
/ 19 апреля 2020

Проблемы возникают из блока else if: когда вы рекурсивно вызываете метод сам по себе, вам также необходимо вызвать resolve() после разрешения вложенного обещания: в противном случае обратный вызов .then() никогда не сработает.

function FindElementById(id, menuItems) {
    return new Promise((resolve) => {
        menuItems.forEach(function (menuItem) {
            if (menuItem.Id === id) {
                return resolve(menuItem);

            } else if (menuItem.Child.length > 0) {
                // You also need to remember to resolve here!
                FindElementById(id, menuItem.Child).then(nestedMenuitem => resolve(nestedMenuitem));
            }
        });
    });
}

Однако существует проблема: обещание может быть разрешено только один раз . Итак, ваше обещание на самом деле разрешается на первой итерации forEach l oop, если выполняется условие . Это то, что вы хотите? Если идентификатор действительно уникален или если в случае дублирования идентификаторов вы хотите вернуть только первый экземпляр, это нормально.

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

function FindElementById(id, menuItems) {
    let el;
    for (let menuItem of menuItems) {
        if (menuItem.Id === id) {
            el = menuItem;
            break;
        } else {
            el = FindElementById(id, menuItem.Child)
        }
    }

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