await promise.all 链式数组方法
await promise.all chained array-methods
我需要递归调用 API 遍历子条目,然后 return 筛选结果,然后再继续。我最初将结果放在一个数组中,然后执行 .forEach
,如果我找到一个匹配项,我需要递归这样做;但是,由于 的答案中描述的问题,这没有用。所以,我试着修改了那个问题的答案,但还是没等到。
const getDatabases = async (blockId) => {
let databases = [];
let childDatabases = [];
const children = await getChildren(blockId);
Promise.all(children.results
.filter( (child) => {
return (['child_database', 'database'].includes(child.type)
|| child.has_children === true);
})
.map( async (child) => {
if (['child_database', 'database'].includes(child.type)) {
return { id: child.id, title: child.child_database.title };
} else {
console.log(`Waiting on getDatabases for ${child.id}`); // 1
childDatabases = await getDatabases(child.id);
return false;
}
})
)
.then((childDbs) => {
console.log(`Got childDbs`); // 3, 4
databases =
[...databases, ...childDatabases].filter(dbId => dbId !== false);
return databases;
})
.catch((err) => console.log(err));
}
app.get('/api', async (req, res) => {
const dashboardPage = await getDashboardPage();
const databases = await getDatabases(dashboardPage);
console.log('No longer awaiting getDatabases'); // 2
...
}
那么问题来了,为什么 2 出现在 3 和 4 之前,而不是在它们之后? 2 之前的 const databases = await getDatabases(dashboardPage);
不应该等待 1 之后通过 childDatabases = await getDatabases(child.id);
的所有递归调用吗?
直接的答案是我需要 await
Promise.all
。否则,Promise.all
在到达 .then
之前挂出并等待其中的 async/await
,但父函数只是触发了这些承诺和 returns没什么,因为没有人告诉它等待。所以,简单地说,
const getDatabases = async (blockId) => {
let databases = [];
let dbsOfChildren = [];
const children = await getChildren(blockId);
await Promise.all(children.results
.filter( (child) => {
值得注意的是,出于类似的原因,不能在 async
之后链接更多的数组方法。否则,下一个链式方法将立即传递一个数组……未解决的承诺。所以,你不能,例如,
await Promise.all(myArray
.filter( (e) => {
// do stuff
})
.map( async (e) => {
// do some async stuff
})
.filter( // filter ); // <-- this won't work
)
相反,您需要等待 promise 解决,然后再进行额外的操作,因此您将其放入 .then
:
await Promise.all(myArray
.filter( (e) => {
// do stuff
})
.map( async (e) => {
// do some async stuff
})
)
.then((myPromisesAreResolvedArray) => {
return myMyPromisesAreResolvedArray.filter( // filter );
})
或者,也许正如评论中指出的那样更好,只需将等待的承诺(您修改的数组)的结果存储在 const
中,然后继续您的代码...
const myPromisesAreResolvedArray = await Promise.all(myArray
.filter( (e) => {
// do stuff
})
.map( async (e) => {
// do some async stuff
})
)
return myPromisesAreResolvedArray.filter( ... );
我需要递归调用 API 遍历子条目,然后 return 筛选结果,然后再继续。我最初将结果放在一个数组中,然后执行 .forEach
,如果我找到一个匹配项,我需要递归这样做;但是,由于
const getDatabases = async (blockId) => {
let databases = [];
let childDatabases = [];
const children = await getChildren(blockId);
Promise.all(children.results
.filter( (child) => {
return (['child_database', 'database'].includes(child.type)
|| child.has_children === true);
})
.map( async (child) => {
if (['child_database', 'database'].includes(child.type)) {
return { id: child.id, title: child.child_database.title };
} else {
console.log(`Waiting on getDatabases for ${child.id}`); // 1
childDatabases = await getDatabases(child.id);
return false;
}
})
)
.then((childDbs) => {
console.log(`Got childDbs`); // 3, 4
databases =
[...databases, ...childDatabases].filter(dbId => dbId !== false);
return databases;
})
.catch((err) => console.log(err));
}
app.get('/api', async (req, res) => {
const dashboardPage = await getDashboardPage();
const databases = await getDatabases(dashboardPage);
console.log('No longer awaiting getDatabases'); // 2
...
}
那么问题来了,为什么 2 出现在 3 和 4 之前,而不是在它们之后? 2 之前的 const databases = await getDatabases(dashboardPage);
不应该等待 1 之后通过 childDatabases = await getDatabases(child.id);
的所有递归调用吗?
直接的答案是我需要 await
Promise.all
。否则,Promise.all
在到达 .then
之前挂出并等待其中的 async/await
,但父函数只是触发了这些承诺和 returns没什么,因为没有人告诉它等待。所以,简单地说,
const getDatabases = async (blockId) => {
let databases = [];
let dbsOfChildren = [];
const children = await getChildren(blockId);
await Promise.all(children.results
.filter( (child) => {
值得注意的是,出于类似的原因,不能在 async
之后链接更多的数组方法。否则,下一个链式方法将立即传递一个数组……未解决的承诺。所以,你不能,例如,
await Promise.all(myArray
.filter( (e) => {
// do stuff
})
.map( async (e) => {
// do some async stuff
})
.filter( // filter ); // <-- this won't work
)
相反,您需要等待 promise 解决,然后再进行额外的操作,因此您将其放入 .then
:
await Promise.all(myArray
.filter( (e) => {
// do stuff
})
.map( async (e) => {
// do some async stuff
})
)
.then((myPromisesAreResolvedArray) => {
return myMyPromisesAreResolvedArray.filter( // filter );
})
或者,也许正如评论中指出的那样更好,只需将等待的承诺(您修改的数组)的结果存储在 const
中,然后继续您的代码...
const myPromisesAreResolvedArray = await Promise.all(myArray
.filter( (e) => {
// do stuff
})
.map( async (e) => {
// do some async stuff
})
)
return myPromisesAreResolvedArray.filter( ... );