javascript - 递归承诺 NodeJS 不会终止
问题描述
我编写了以下函数来重建包含递归的 JSON 对象。但是在执行时,它不会在执行时返回任何console.log
内容,并且一次又一次地记录相同的组件而不会终止。任何人都可以帮我确定问题吗?
this.findOne = (id) => {
return new Promise(resolve => {
componentCollection.find(id).then(components => {
if (components[0]) {
let subComponents = components[0].components;
for (let i = 0; i < subComponents.length; i++) {
console.log(subComponents[i])
subComponents[i] = resolve(this.findOne(subComponents[i].id))
}
components[0].components = subComponents;
}
resolve(components[0])
})
})
}
编辑: 组件包括仅包含 id 作为属性。这就是为什么我必须像这样递归地构建它。我尝试了另一种方式,结果是相同的无限日志:
this.findOne = async (id) => {
let components = await componentCollection.find(id)
if (components[0]) {
let subComponents = components[0].components;
for (let i = 0; i < subComponents.length; i++) {
console.log(subComponents[i])
subComponents[i] = await this.findOne(subComponents[i].id)
}
components[0].components = subComponents;
}
return components[0]
}
两者都尝试一次又一次地记录父组件的第一个子组件。
我尝试构建的对象:
{
id:1,
name:"comp1",
components:[
{
id:2,
name:"comp2",
components:[
{
id:3,
name:"comp3"
},
{
id:4,
name:"comp4"
}
]
}
]
}
控制台无限日志来自console.log(subComponents[i])
:
{
id:2,
name:"comp2",components:[..]
}
编辑:
findOne 的周边代码:
this.findone = () =>{}
module.exports = {
findOne: this.findOne
};
我在控制器中将其称为:
const ComponentService = require('./cs');
const component = await ComponentService.findOne(id)//id={1,2,...}
解决方案
这是一个使用 Promises 的版本。大概很容易将其转换为async-await
. 它使用纯函数,而不是对象的方法。这不应该太难改变;我没有尝试过,但您可能必须存储一个本地引用才能this
使其工作。
const findOne = (id) => new Promise (
(resolve, reject) =>
componentCollection .find (id) .then (
({components = [], ...rest}) =>
Promise .all (components .map (({id}) => findOne (id))) .then (
children => resolve ({...rest, components: children}),
reject
),
reject
)
)
findOne (5) .then (console .log, console .warn)
findOne (1) .then (console .log, console .warn)
.as-console-wrapper {min-height: 100% !important; top: 0}
<script>
// Dummy code just for demonstration
const componentCollection = {
find: (n) => [1, 2, 3, 4] .includes (n)
? Promise .resolve (
n == 1
? {id: 1, name: 'comp1', components: [{id: 2}]}
: n == 2
? {id: 2, name: 'comp2', components: [{id: 3}, {id: 4}]}
: n == 3
? {id: 3, name: 'comp3'}
: {id: 4, name: 'comp4'}
)
: Promise .reject (`Not found: ${n}`)
}
</script>
这里的要点是用于Promise.all
将子组件的 Promise 列表转换为单个 Promise,然后您可以附加到该 Promise 上。
推荐阅读
- javascript - 在鼠标按下/输入时重置文本字段 - jQuery UI 自动完成
- hibernate - 使用 JPA/Hibernate 映射具有共享列的复合主键和外键
- php - 在另一个 html 文件中提交按钮时运行 php 文件
- http - 如何使用 ANT 打印 exec 错误代码
- swift - 时间和日期计算
- ios - “launchPackager.command”无法打开,因为它来自身份不明的开发者
- javascript - Ionic 4 为 Android 和 iOS 返回不同的时间值
- java - 我可以在不丢失代码的情况下重新导入已删除的 .git 文件吗?
- android - 启用安全参数插件后无法从数据绑定获取根视图
- docker - docker node ls 不会将提升节点的管理器状态更改为可访问