【问题标题】:Promise not returned from recursive function递归函数未返回承诺
【发布时间】:2020-04-19 19:08:49
【问题描述】:

背景

我有一个问题,我的承诺没有返回到它的调用函数。我知道这通常会起作用,但不是在递归函数中。正在调用解析,我可以看到函数 FindElementById 正在正确找到元素,但是未调用 thenable UpdateMasterMenuItem(result, queuedItem) 中的调用。

我在我的代码 sn-ps 中做了什么,我想做什么?

遍历集合 queuedItems 并在另一个集合 menuItems 中找到这些项目。我通过将我要查找的项目的 ID 以及它所在的集合传递给递归函数 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);
            }
        });
    });
}

【问题讨论】:

  • FindElementById 返回承诺是否有原因?该方法中没有任何异步操作。

标签: javascript recursion promise


【解决方案1】:

问题来自else if 块:当您递归调用该方法本身时,您还需要在解决嵌套的promise 后调用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 循环的第一次迭代中得到解决。那是你要的吗?如果 ID 确实是唯一的,或者在重复 ID 的情况下您只想返回第一个实例,那么这没关系。

这让我们回到我的评论:你的函数没有做任何异步操作,所以完全不用承诺可能更容易做到:

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

【讨论】:

  • 好点。经过反思,我似乎决定尝试使用 Promise 作为我没有正确理解的问题的解决方案。
猜你喜欢
  • 2019-05-25
  • 2017-05-09
  • 2018-10-11
  • 2020-01-24
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 2016-05-07
相关资源
最近更新 更多