如何等待异步调用完成
How to wait for async calls to finish
我正在 运行 三个 API 使用 Spotify API 调用,以便获取以下数据并将它们存储到我的Artist
对象:
- 艺术家。
- 那个艺术家的专辑。
- 艺术家每张专辑的曲目。
完成后,我想将对象传递给不同的视图控制器。它看起来像这样:(如果有必要的话 post 所有 NSURLSession
代码)
func getArtist(artistName) {
getAlbums(artistIdString)}
func getAlbums(artistIdString) {
a = Album
Artist.albumsArray.append(a)
for album in Artist.albumsArray {
getTracks(albumIdString)
}
}
func getTracks (albumIdString) {
t = Track
for album in Artist.albumsArray {
if idString == albumIdString {
album.append(t)
}
}
}
func passArtist {
DataStore.sharedInstance().Artist = Artist
}
首先,您如何同时进行三个 API 调用?
还是用户先选择艺术家,然后你调用获取专辑,然后显示专辑,然后用户选择专辑,你进行第三次请求?
无论哪种方式,我建议你把AsyncTask class写在Activityclass里面,然后你可以用一个计数器等待三个调用完成,然后on onPostExecute() 方法,您可以构建一个 Parcelable 对象并将其传递到包中(intent.putExtra(authorObject) 以在第二个 Activity.
的 onCreate 方法中接收它
然后显示请求的信息(我猜你是把它存储在数据库中进行缓存)
在NSURLSession
(或NSURLSessionDataTask
)的回调function/block(或Apple术语中的完成处理程序)中,运行 针对当前 Artist
对象的检查函数,查看是否所有 3 个必需元素都存在(如果存在,调用 passArtist
)。
无论完成顺序如何,如果您这样做,它最终会在完成获取 3 个元素后调用 passArtist
。
这里有一个简单的例子来证明 Objective-C 中的想法(根据 OP 的要求):
- (void)getArtistDataWithRequest:(NSURLRequest *)request
{
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error)
{
if (error)
{
// Something went wrong, fallback.
NSLog(@"An error occurred: %@", error.localizedDescription);
// You could use some error handler e.g.:
// [self connectionDidFailWithError:error];
return;
}
else if (response)
{
// Seems working, moving forward.
[self connectionDidReceiveSpotifyServerResponse:response
andData:data];
}
}];
[task resume];
}
- (void)connectionDidReceiveSpotifyServerResponse:(NSURLResponse *)aResponse
andData:(NSData *)aResponseData
{
// Do what you want here with the data you get, either it's album, track,
// or whatever.
// Assuming your "Artist" property is named "myArtist", and the "Artist"
// class has a method to process the data you get from Spotify API:
[_myArtist handleArtistData:aResponseData];
// Now check your Artist object's element with another method. e.g.:
if ([_myArtist isLoadingComplete])
{
// Done loading the object, pass it to view controller.
}
// Not yet done, do nothing for now.
}
这只是一种解决方案。一旦你有了想法,有很多方法可以实现你想要的。
2.5 年后回到这里。我正在寻找的是完成语法,尽管当时我不知道那是什么或如何寻求帮助。
func getArtist(artistName: String, completion: (Artist) -> ()) {
getAlbums(artistIdString)
}
希望这对遇到此问题的任何人有所帮助。
我正在 运行 三个 API 使用 Spotify API 调用,以便获取以下数据并将它们存储到我的Artist
对象:
- 艺术家。
- 那个艺术家的专辑。
- 艺术家每张专辑的曲目。
完成后,我想将对象传递给不同的视图控制器。它看起来像这样:(如果有必要的话 post 所有 NSURLSession
代码)
func getArtist(artistName) {
getAlbums(artistIdString)}
func getAlbums(artistIdString) {
a = Album
Artist.albumsArray.append(a)
for album in Artist.albumsArray {
getTracks(albumIdString)
}
}
func getTracks (albumIdString) {
t = Track
for album in Artist.albumsArray {
if idString == albumIdString {
album.append(t)
}
}
}
func passArtist {
DataStore.sharedInstance().Artist = Artist
}
首先,您如何同时进行三个 API 调用? 还是用户先选择艺术家,然后你调用获取专辑,然后显示专辑,然后用户选择专辑,你进行第三次请求?
无论哪种方式,我建议你把AsyncTask class写在Activityclass里面,然后你可以用一个计数器等待三个调用完成,然后on onPostExecute() 方法,您可以构建一个 Parcelable 对象并将其传递到包中(intent.putExtra(authorObject) 以在第二个 Activity.
的 onCreate 方法中接收它然后显示请求的信息(我猜你是把它存储在数据库中进行缓存)
在NSURLSession
(或NSURLSessionDataTask
)的回调function/block(或Apple术语中的完成处理程序)中,运行 针对当前 Artist
对象的检查函数,查看是否所有 3 个必需元素都存在(如果存在,调用 passArtist
)。
无论完成顺序如何,如果您这样做,它最终会在完成获取 3 个元素后调用 passArtist
。
这里有一个简单的例子来证明 Objective-C 中的想法(根据 OP 的要求):
- (void)getArtistDataWithRequest:(NSURLRequest *)request
{
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error)
{
if (error)
{
// Something went wrong, fallback.
NSLog(@"An error occurred: %@", error.localizedDescription);
// You could use some error handler e.g.:
// [self connectionDidFailWithError:error];
return;
}
else if (response)
{
// Seems working, moving forward.
[self connectionDidReceiveSpotifyServerResponse:response
andData:data];
}
}];
[task resume];
}
- (void)connectionDidReceiveSpotifyServerResponse:(NSURLResponse *)aResponse
andData:(NSData *)aResponseData
{
// Do what you want here with the data you get, either it's album, track,
// or whatever.
// Assuming your "Artist" property is named "myArtist", and the "Artist"
// class has a method to process the data you get from Spotify API:
[_myArtist handleArtistData:aResponseData];
// Now check your Artist object's element with another method. e.g.:
if ([_myArtist isLoadingComplete])
{
// Done loading the object, pass it to view controller.
}
// Not yet done, do nothing for now.
}
这只是一种解决方案。一旦你有了想法,有很多方法可以实现你想要的。
2.5 年后回到这里。我正在寻找的是完成语法,尽管当时我不知道那是什么或如何寻求帮助。
func getArtist(artistName: String, completion: (Artist) -> ()) {
getAlbums(artistIdString)
}
希望这对遇到此问题的任何人有所帮助。