我一直试图弄清楚如何解决这个问题,但失败了。基本上我正在构建一个具有以下结构的数据树:
tree = [
{
'title': 'Company 1',
'children': [
{
'title': 'Opportunity 1',
'children': [
{
'title': 'Library 1'
}, // library
{
'title': 'Library 2'
} // library
]
}, // opportunity
{
'title': 'Opportunity 2',
'children': [
{
'title': 'Library 1'
}, // library
{
'title': 'Library 2'
} // library
]
}, // opportunity
]
}, // client
...
]
我编写了以下代码,它可以很好地填充树节点,我只是不知道如何找出填充过程何时完成并且树可以使用了。
您对如何处理这个有什么想法吗?
getList(getGetSitesURL(site)).then(r => {
r.d.results.map(site => {
var client = {};
client['title'] = site.Title;
getList(getGetSitesURL(site.ServerRelativeUrl)).then(r => {
r.d.results.map(site => {
var opportunity = {};
var opportunities = [];
opportunity['title'] = site.Title;
getLibrary(getGetLibrariesURL(site.ServerRelativeUrl)).then(r => {
r.d.results.map(lib => {
var library = {};
var libraries = [];
library['title'] = lib.Title;
libraries.push(library);
opportunity['children'] = libraries;
opportunities.push(opportunity);
client['children'] = opportunities;
tree.push(client);
})
})
});
})
})
})
编辑:我刚刚发现这个解决方案不能正常工作,我最终在树形数组中有重复项。也许有人可以告诉我如何以不同的方式处理这个问题。感谢。
答案 0 :(得分:1)
有几个问题:
client
个对象,这意味着您通常会获得太多的对象。 map
时,您应该将其用作push
的替代方法,因为它会返回一个数组,从而无需使用push
并导致更多功能代码。libraries
在每次[]
次迭代中重置为map
:这可能不正确,并且每次都会导致只有一个元素的数组,您需要获得尽可能多的元素map
的元素正在迭代。then
回调中处理它。这是一个应该有效的实现:
getList(getGetSitesURL(site)).then(r =>
Promise.all(r.d.results.map(site =>
getList(getGetSitesURL(site.ServerRelativeUrl)).then( r =>
Promise.all(r.d.results.map(subsite =>
getLibrary(getGetLibrariesURL(subsite.ServerRelativeUrl)).then(r => ({
title: subsite.Title,
children: r.d.results.map(lib => ({ title: lib.Title }))
}))
)).then(children => ({ title: site.Title, children}))
)
))
).then(tree => {
console.log(JSON.stringify(tree, null, 2));
});
输出类似于:
[
{
"title": "Company1",
"children": [
{
"title": "Opportunity 1",
"children": [
{
"title": "Library 1"
},
{
"title": "Library 2"
}
]
},
{
"title": "Opportunity 1",
"children": [
{
"title": "Library 1"
},
{
"title": "Library 2"
}
]
}
]
}
]
请注意,上面的代码使用带有表达式语法的箭头函数而不是语句块语法(因此在胖箭头=>
之后没有括号)。胖箭头后面的表达式被计算为此箭头函数的 return 值。要使用语句块语法执行相同的操作,您可以将=> expression
更改为=> { return expression; }
。
答案 1 :(得分:0)
如果您从.then()
处理程序中返回承诺,那么这些承诺将被添加到链中,您可以通过监视顶级承诺来判断事情何时完成。此外,无论您在一个范围内创建多个承诺,您都可以监视所有这些承诺何时完成Promise.all()
并返回一个主承诺。
以下是您在展示的代码中的工作原理。变更摘要:
您运行.map()
并创建多个承诺的任何地方,请在生成的承诺数组中使用Promise.all()
,以了解它们何时完成。
在.map()
回调中,返回您创建的承诺,以便.map()
的结果为一系列承诺,然后您可以Promise.all()
使用。{/ p>
在运行任何异步操作的每个.then()
处理程序中,返回一个监视异步操作的promise,然后将其链接到父promise。
在顶级承诺上使用.then()
知道所有链接的内部承诺何时确实完成。
以下是如何将其应用于您展示的代码。
getList(getGetSitesURL(site)).then(r => {
// Use Promise.all() to know when the array of promises are all done
return Promise.all(r.d.results.map(site => {
var client = {};
client['title'] = site.Title;
// return this promise so .map() results in an array of promises
return getList(getGetSitesURL(site.ServerRelativeUrl)).then(r => {
// Use Promise.all() to know when the array of promises are all done
return Promise.all(r.d.results.map(site => {
var opportunity = {};
var opportunities = [];
opportunity['title'] = site.Title;
// return this promise so .map() results in an array of promises
return getLibrary(getGetLibrariesURL(site.ServerRelativeUrl)).then(r => {
r.d.results.map(lib => {
var library = {};
var libraries = [];
library['title'] = lib.Title;
libraries.push(library);
opportunity['children'] = libraries;
opportunities.push(opportunity);
client['children'] = opportunities;
tree.push(client);
});
});
}));
});
}));
}).then(function() {
// all done here
}).catch(function(err) {
// some error here
});