如何等到所有异步调用完成
How to wait until all async calls are finished
我有 NestJS 应用程序,它与 YoutubeAPI 交互并从中加载视频。
一种特定的方法很重要,它是下面的 loadVideos
。方法它自己内部有多个异步,我需要在一切完成后使用 videoIdMap
属性
private loadVideos(
playListId: string,
channel: Channel,
nextPageToken: string,
stopLoadingOnVideoId: string,
) {
const baseUrl = YoutubeService.VIDEO_URL_SNIPPET_BY_ID + playListId;
const response = this.httpService
.get(nextPageToken ? baseUrl + '&pageToken=' + nextPageToken : baseUrl)
.pipe(map((response) => response.data));
response.subscribe((data) => {
data.items.forEach((item) => {
if (stopLoadingOnVideoId && item.snippet.resourceId.videoId === stopLoadingOnVideoId) {
return;
}
this.prepareVideoEntity(item.snippet, channel).then((partialVideo) =>
this.videoService.create(partialVideo).then((video) => {
this.videoIdMap[video.youtubeId] = video.id;
}),
);
});
if (data.nextPageToken) {
this.loadVideos(
playListId,
channel,
data.nextPageToken,
stopLoadingOnVideoId,
);
}
});
}
对我来说理想的解决方案是以某种方式使 loadVideos
异步,这样我以后可以做:
public methodWhichCallLoadVideos(): void {
await loadVideos(playListId, channel, null, stopLoadingOnVideoId)
// My code which have to be executed right after videos are loaded
}
我尝试过的每个解决方案都以 this.videoIdMap
为空对象或存在编译问题而告终,因此欢迎任何想法。
您可以切换到 promises 而不是 Observables,从而将方法变成异步方法,只要 data
有一个 nextPageToken
:
private async loadVideos(
playListId: string,
channel: Channel,
nextPageToken: string,
stopLoadingOnVideoId: string,
) {
const baseUrl = YoutubeService.VIDEO_URL_SNIPPET_BY_ID + playListId;
const response = await this.httpService
.get(nextPageToken ? url + '&pageToken=' + nextPageToken : url).toPromise();
const { data } = response;
for (const item of data.items) {
if (stopLoadingOnVideoId && item.snippet.resourceId.videoId === stopLoadingOnVideoId) {
continue;
}
const partialVideo = await this.prepareVideoEntity(item.snippet, channel);
const video = await this.videoService.create(partialVideo)
this.videoIdMap[video.youtubeId] = video.id;
}
if (data.nextPageToken) {
await this.loadVideos(
playListId,
channel,
data.nextPageToken,
stopLoadingOnVideoId,
);
}
}
在你的来电者中你可以简单地等待 loadVideos(...)
:
private async initVideoIdMap(...) {
await this.loadVideos(...);
// this.videoIdMap should be correctly populated at this point
}
我有 NestJS 应用程序,它与 YoutubeAPI 交互并从中加载视频。
一种特定的方法很重要,它是下面的 loadVideos
。方法它自己内部有多个异步,我需要在一切完成后使用 videoIdMap
属性
private loadVideos(
playListId: string,
channel: Channel,
nextPageToken: string,
stopLoadingOnVideoId: string,
) {
const baseUrl = YoutubeService.VIDEO_URL_SNIPPET_BY_ID + playListId;
const response = this.httpService
.get(nextPageToken ? baseUrl + '&pageToken=' + nextPageToken : baseUrl)
.pipe(map((response) => response.data));
response.subscribe((data) => {
data.items.forEach((item) => {
if (stopLoadingOnVideoId && item.snippet.resourceId.videoId === stopLoadingOnVideoId) {
return;
}
this.prepareVideoEntity(item.snippet, channel).then((partialVideo) =>
this.videoService.create(partialVideo).then((video) => {
this.videoIdMap[video.youtubeId] = video.id;
}),
);
});
if (data.nextPageToken) {
this.loadVideos(
playListId,
channel,
data.nextPageToken,
stopLoadingOnVideoId,
);
}
});
}
对我来说理想的解决方案是以某种方式使 loadVideos
异步,这样我以后可以做:
public methodWhichCallLoadVideos(): void {
await loadVideos(playListId, channel, null, stopLoadingOnVideoId)
// My code which have to be executed right after videos are loaded
}
我尝试过的每个解决方案都以 this.videoIdMap
为空对象或存在编译问题而告终,因此欢迎任何想法。
您可以切换到 promises 而不是 Observables,从而将方法变成异步方法,只要 data
有一个 nextPageToken
:
private async loadVideos(
playListId: string,
channel: Channel,
nextPageToken: string,
stopLoadingOnVideoId: string,
) {
const baseUrl = YoutubeService.VIDEO_URL_SNIPPET_BY_ID + playListId;
const response = await this.httpService
.get(nextPageToken ? url + '&pageToken=' + nextPageToken : url).toPromise();
const { data } = response;
for (const item of data.items) {
if (stopLoadingOnVideoId && item.snippet.resourceId.videoId === stopLoadingOnVideoId) {
continue;
}
const partialVideo = await this.prepareVideoEntity(item.snippet, channel);
const video = await this.videoService.create(partialVideo)
this.videoIdMap[video.youtubeId] = video.id;
}
if (data.nextPageToken) {
await this.loadVideos(
playListId,
channel,
data.nextPageToken,
stopLoadingOnVideoId,
);
}
}
在你的来电者中你可以简单地等待 loadVideos(...)
:
private async initVideoIdMap(...) {
await this.loadVideos(...);
// this.videoIdMap should be correctly populated at this point
}