在带有打字稿的节点应用中,我需要通过数组迭代,并在循环中调用异步函数,以获取有关数组中每个项目的相关项目的信息。每个相关项目都调用该函数以在RelactionItems数组中获取其标题。
我能够检索第二级数组的承诺(相关标准),但不确定一旦顶级完成,如何实现A。
如何通过承诺实现我的目标。
var Inputarray = [
{ Category: "cat1"
relatedItems: [
{id: "1"},
{id: "2"},
{id: "3"}
]
},
{
Category: "cat2"
relatedItems: [
{id: "1"},
{id: "2"},
{id: "3"}
]
}
];
var wantedresult= [
{ Category: "cat1"
relatedItems: [
{Title: "xxx"},
{Title: "yyy"},
{Title: "zzz"}
]
},
{
Category: "cat2"
relatedItems: [
{Title: "ttt"},
{Title: "kkk"},
{Title: "mmm"}
]
}
];
private GetAllRelattedItems(data: IListItem[]): any{
let rendredItems: RelatedItem[] = new Array();
data.forEach(item => {
let relatedItemsinfos : relatedItemInfos[]=item.Children;
let localTab:relatedItem[]=new Array();
let newItem = {
Category:item.Category,
Children: []
};
var promises = [];
relatedItemsinfos.forEach(relatedItemsInfositem =>{
promises.push(this.GetRelatedItem(relatedItemsInfositem.WebId,relatedItemsInfositem.ListId,relatedItemsInfositem.ItemId));
});
Promise.all(promises).then(function(response) {
response.forEach(obj=>{
let newNode: relatedItem ={
Title :Obj.Title,
};
newItem.Children.push(newNode);
});
rendredItems.push(newItem);
});
});
}
private GetRelatedItem(id:string) : Promise<relatedItem> {
return new Promise((resolve) => {
pnp.sp.site.openWeb()
.then(web => {
//this.getWeb()
//.then((web) => {
return web.web.lists.getList().get(); //w.web.lists.getById("").get().then(r => {
})
.then((list) => {
return this.getItem(list,id);
})
.then((item) => {
resolve(item);
});
});
}
您应该在顶级使用Promise.all
,然后返回数据数组中每个项目的承诺:
private GetAllRelattedItems(data: IListItem[]): any {
//..
let allData = data.map(item => {
//..
return Promise.all(promises).then(function (response) {
//..
});
});
Promise.all(allData).then (_=> { /* After all data is retrieved */})
}
,由于您正在使用Typescript的一种更好的方法是利用async/await
使代码更可读:
private async GetAllRelattedItems(data: IListItem[]): Promise<RendredItem[]> {
let allData = data.map(async item => {
let relatedItemsinfos: relatedItemInfos[] = item.Children;
let localTab: relatedItem[] = new Array();
let newItem = {
Category: item.Category,
Children: []
};
var response = await Promise.all(relatedItemsinfos.map(relatedItemsInfositem => {
return this.GetRelatedItem(relatedItemsInfositem.WebId);
}));
newItem.Children = response.map(entry => ({
Title: entry.value[0].Title,
FileLeafRef: entry.value[0].FileLeafRef,
Modified: entry.value[0].Modified,
FileRef: entry.value[0].FileRef,
FieldValuesAsText: {
FileRef: entry.value[0].FileRef,
}
}));
return newItem;
});
var result = await Promise.all(allData);
// After all results are done
return result
}
private async GetRelatedItem(id: string): Promise<{ value: relatedItem[] }> {
const web = await pnp.sp.site.openWeb()
const list = await web.web.lists.getList().get(); //w.web.lists.getById("").get().then(r => {
return await this.getItem(list,id);
}
// Placeholder
public getItem(list: any[], id: string ): Promise<{ value: relatedItem[] }>{
return Promise.resolve({
value : []
});
}
注意我猜测一些基于用法的类型,您应该查看以确保它们正确。
private async GetAllRelattedItems(data: IListItem[]): Promise<RendredItem[]> {
let allData = data.map(async item => {
let relatedItemsinfos: relatedItemInfos[] = item.Children;
let localTab: relatedItem[] = new Array();
let newItem = {
Category: item.Category,
Children: []
};
var response = await Promise.all(relatedItemsinfos.map(relatedItemsInfositem => {
return this.GetRelatedItem(relatedItemsInfositem);
}));
newItem.Children = response.map(entry => ({
Title: entry.value[0].Title,
FileLeafRef: entry.value[0].FileLeafRef,
Modified: entry.value[0].Modified,
FileRef: entry.value[0].FileRef,
FieldValuesAsText: {
FileRef: entry.value[0].FileRef,
}
}));
return newItem;
});
var result = await Promise.all(allData);
// After all results are done
return result
}
private async GetRelatedItem(relatedItemsInfositem) : Promise<any> {
const web = await pnp.sp.site.openWebById(relatedItemsInfositem.WebId);
const list = await web.web.lists.getById(relatedItemsInfositem.ListId).get();
return await this.getItem(list,relatedItemsInfositem.ItemId);
// here i would like to call GetItemSize that is async and that take return the size as a number but i would like to return the whole item model
}
public getItem(list: any, itemId: string): Promise<any>{
let url: string;
if(list.ParentWebUrl !='/'){
url= list.ParentWebUrl + "/_api/web/lists/getbytitle('"+list.Title+"')/items?$select=FileLeafRef,FileRef,Title,File/ServerRelativeUrl,Modified,FieldValuesAsText/FileRef&$expand=File&$expand=FieldValuesAsText&$filter=Id eq "+itemId;
}
else url="/_api/web/lists/getbytitle('"+list.Title+"')/items?$select=FileLeafRef,FileRef,Title,File/ServerRelativeUrl,Modified,FieldValuesAsText/FileRef&$expand=FieldValuesAsText&$expand=File&$filter=Id eq "+itemId;
return this.context.spHttpClient.get(url,SPHttpClient.configurations.v1).then((response: Response)=>{
return response.json();
});
}
private async GetItemSize(title: string): Promise<relatedItem>{
let url:string ;
let response = await this.context.spHttpClient.get(url ,SPHttpClient.configurations.v1);
// Asuming the json has the shape of relatedItem : Here the response is just a number and not shaped RelatedItem the goal is to return the whole relatedItem with size information.
return <relatedItem>response.json(); }