express - 如何等待所有异步调用完成

标签 express promise observable es6-promise nestjs

我有 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 成为空对象或出现编译问题,因此任何想法都非常受欢迎。

最佳答案

您可以切换到 Promise 而不是 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
}

关于express - 如何等待所有异步调用完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64374671/

相关文章:

javascript - 我无法到达 "/campgrounds/:id/comments/new"

JavaScript异步: Log the response from each action in the order it was called

java - MetaController 应该观察三个对象

typescript - 将 Observable 对象中的数组与 ngFor 和 Async Pipe Angular 2 结合使用

node.js - 从一个 Connect 中间件访问另一个中间件的最佳方式是什么?

node.js - NodeJS Express 对 URL 进行编码 - 如何解码

javascript - expressjs POST header 参数?

javascript - 使用 console.log 作为 promise 回调

Javascript Promise 与 jQuery Deferred

javascript - RxJS: BehaviorSubject 退订