这是公司一位小朋友的代码,他很疑惑为什么info是undefined;
let list = [
{
type: 5,
name: '创建节点',
ondid: 'd8b30f2e',
flowNodeType: 'node',
propObj: { bgType: 5, topName: '创建节点', contentName: '申请人', flag: -1, list: [] },
},
{
ondid: 'f97f3da8',
flowNodeType: 'branchbox',
list: [
{ flowNodeType: 'branch', ondid: '71edab98', propObj: { list: [] } },
{ flowNodeType: 'branch', ondid: '5936d6f4', propObj: { list: [] } },
],
},
];
let obj = {
flowNodeType: 'branch',
ondid: '5936d6f4',
};
let obj = {
flowNodeType: 'branch',
ondid: 'tmp-5936d6f4-ddfb-4254-8902-69198e10f8db-branch',
};
async function getIndex(ondid, list) {
let index = list.findIndex((item) => item.ondid == ondid);
return index;
}
/**
* 分支消息
* @param {*} obj
* @param {*} list
*/
async function getBranchInfo(obj, list) {
let index = getIndex(obj.ondid, list);
if (index >= 0) {
return list[index];
}
list.forEach((item) => {
if (item.flowNodeType == 'branchbox') {
item.list.forEach((row) => {
getBranchInfo(obj, item.list);
});
} else if (item.flowNodeType == 'branch') {
item.propObj.list.forEach((item) => {
getBranchInfo(obj, item.propObj.list);
});
}
});
}
// 递归循环获取对象数据 先获取 { { { a=1} } }
async function serachInfo(obj, list) {
if (obj.flowNodeType == 'node') {
// ...
} else if (obj.flowNodeType == 'branch') {
let info = await getBranchInfo(obj, list);
console.log(info); // ??? 为什么是undefined
}
}
serachInfo(obj, list);
首先这段代码里有几个明显的问题?
1、forEach中使用return是无效的。
2、还有一个问题,async function xxx 的返回值是promise,需要用await来接收,并且都是同步代码,不需要用async/await来包裹。
3、getBranchInfo函数职责不单一
改造意见:
1、getBranchInfo职责单一化,可以将查找list的逻辑抽离到searchInfo中,getBranchInfo只用来判断当前传入的list是否含有符合条件的节点。
2、findIndex获取index,然后又从list[index]获取节点,其实也不必这么麻烦,可以用Array.find实现,不用这么麻烦,第一个就可以直接忽略了
3、searchInfo中,利用方式广度优先的策略,将list的所有子list合并成一个数组,作为参数,递归传入searchInfo中,递归结束条件:调用getBranchInfo获取到符合条件的节点。
改造以后的代码
function searchInfo (obj, list) {
let info = list.find(item => {
return item.ondid === obj.ondid
})
if (info) {
return info
}
let nextLevel = []
for (let item of list) {
if (item.flowNodeType === 'node') {
nextLevel = nextLevel.concat(item.propObj.list)
} else {
nextLevel = nextLevel.concat(item.list)
}
}
return searchInfo(obj, nextLevel)
}
console.log(searchInfo(obj, list))