Swift async/await 等同于 Promise Kit "when" 模式



我是Swift的新手,来自JS,我已经开始构建一个iOS应用程序。

最初,我使用Promise Kit来处理异步内容,因为它对我来说似乎比我读到的其他东西更容易。

无论如何,在JS中,我经常使用以下模式:

async function doAyncFunction(item) {
try {
// do async call to fetch data using item
return Promise.resolve(data);
} catch (error) {
return Promise.reject(error);
}
}
const promises = items.map((item) => doAyncFunction(item));
const results = await Promise.all(promises);

我最终通过Promise Kit这样的东西得到了这个:

func doManyAsyncRequests(userIds: [String], accessToken: String) -> Promise<Void> {
Promise { seal in
let promises = spotifyUserIds.map {
doSingleAsyncRequest(userId: $0.id, accessToken: accessToken) // this function returns a promise
}
when(fulfilled: promises).done { results in
print("Results: (results)")
// process results
}.catch { error in
print("(error)")
// handle error
}
}
}

Promise Kit的when与JavaScript的Promise.all()类似,因为一旦实现了承诺,就会触发代码中的内容。

由于我的学习曲线足够慢,我决定开始为iOS 15编码,并使用Swift async/await。

问题:什么Swift async/await模式可以实现上述功能,类似于Promise Kit的wait和JavaScript的Promise.all()

谢谢。

更新:感谢@workingdog,他帮助我找到了下面的解决方案。我现在要处理错误,但现在这是另一个话题了。

func getAllThings(users: [User], accessToken: String) async -> [Thing] {
var allThings: [Thing] = []
await withTaskGroup(of: [Thing].self) { group in
for user in users {
group.async {
let userThings = await self.getUsersThings(
accessToken: accessToken,
displayName: user.displayName,
userId: user.id
)
return userThings
}
}
for await (userThings) in group {
allThings = allThings + userThings
}
}
return allThings
}

您可能正在查找withTaskGroup(...),例如:

func getAll() async {
await withTaskGroup(of: Void.self) { group in
await getPosts()
for post in posts {
group.async { await self.getCommentsFor(post: post) }
}
}
}

我已经在github上设置了自己的基本测试来学习这一点:https://github.com/workingDog/TestAsync

编辑:

这就是我将如何返回一系列带有他们评论的帖子。正如您所看到的,它不如getAll((那么整洁。

func getAllPosts() async -> [Post] {
// this is the tricky parameter bit, the tuple returned when you call group.async {...}
await withTaskGroup(of: (Int, [Comment]).self) { group in
// get all the posts
var thePosts: [Post] = await fetchThem()
// for each post get all the comments (concurrently)
for post in thePosts {
group.async {
let comments: [Comment] = await self.fetchThem(with: post)
return (post.id, comments)
}
}
// add the comments to their corresponding post (concurrently)
for await (postid, comnts) in group {
if let ndx = thePosts.firstIndex(where: {$0.id == postid}) {
thePosts[ndx].comments = comnts
}
}
// when all done, return all post with their comments all cooked up
return thePosts
}
}