如何在ngOnInit中使用await / async?

时间:2018-07-18 16:52:09

标签: angular typescript ecmascript-6

我试图在 ngOnInit() 中调用一个函数并将其提供两个值。因此,这是我尝试在ngOnInit内部调用的函数: this.complexWordIdentification(this.postIWant, this.theHardWords);

这里的问题是this.postIWantthis.theHardWords本身在ngOnInit中得到了解决,如下所示,这导致了错误。现在,我如何调用 this.complexWordIdentification(this.postIWant, this.theHardWords); 并将其输入这些值而又不会出错?

我一直在考虑等待功能吗?但是我无法弄清楚,请问对此有何建议?

这是我的ngOnInit

ngOnInit() {
    this.isLoading = true;
    this.wordsLoaded = false;
    this.postLoaded = false;
    this.form = new FormGroup({
      annotation: new FormControl(null, {
        validators: [
          Validators.required,
          Validators.minLength(8),
          Validators.maxLength(250)
        ]
      })
    });
    this.id = this.route.snapshot.paramMap.get('postId');
    this.annotationService.getWords();
    this.annotationSub = this.annotationService
      .getWordUpdateListener()
      .subscribe((thewords: ComplexWord[]) => {
        this.thewords = thewords;
        this.thewords.map(word => {
          this.theHardWords.push(word.word);
          this.wordWithAnnotation.push(word);
        });
        this.wordsLoaded = true;
        this.isLoading = this.postLoaded && this.wordsLoaded;
      });
    this.postsService.getPosts();
    this.postsSub = this.postsService
      .getPostUpdateListener()
      .subscribe((posts: Post[]) => {
        this.posts = posts;
        this.posts.map(post => {
          if (post.id === this.id) {
            this.postIWant = post.fileText;
          }
        });
        this.postLoaded = true;
        this.isLoading = !(this.postLoaded && this.wordsLoaded);
      });
    this.role = this.authService.getUserRole();
    this.userIsAuthenticated = this.authService.getIsAuth();
    this.authStatus = this.authService
      .getAuthStatus()
      .subscribe(isAuthenticated => {
        this.userIsAuthenticated = isAuthenticated;
        this.role = this.authService.getUserRole();
      });
}

如果有人能指出我正确的方向,那将非常好,因为我在这一领域经验不足。目前,我不得不在this.complexWordIdentification(this.postIWant, this.theHardWords);之外调用ngOnInit来避免该错误,但是显然,我想自动调用它。

3 个答案:

答案 0 :(得分:5)

forkJoin将两个订阅合并为一个订阅,并返回其结果数组。当您需要多个来源的数据才能完成组件的加载时,在ngOnInit中使用它非常有用。

https://www.learnrxjs.io/operators/combination/forkjoin.html

import { Observable } from "rxjs/Observable";
    Observable.forkJoin(
        this.annotationService.getWordUpdateListener(),
        this.postsService.getPostUpdateListener()
    ).subscribe((data) => {
         // data[0] result from getWordUpdateListener
         this.thewords = data[0];
            this.thewords.map(word => {
              this.theHardWords.push(word.word);
              this.wordWithAnnotation.push(word);
            });
            this.wordsLoaded = true;

         // data[1] result from getPostUpdateListener
         this.posts.map(post => {
              if (post.id === this.id) {
                this.postIWant = post.fileText;
              }
            });
            this.postLoaded = true;
        this.isLoading = false;
        this.complexWordIdentification(this.postIWant, this.theHardWords);
    }, (err) => {
        // error handling
    });

edit:在RXJS 5及以下版本中添加了可观察到的导入语句

编辑:RXJS 6更新,更改导入语句

import { forkJoin} from 'rxjs';
forkJoin(this.annotationService.getWordUpdateListener(),
            this.postsService.getPostUpdateListener()
).subscribe((data) => { \\do stuff}, (err) => { \\ do error stuff}

答案 1 :(得分:1)

因为您一次需要两个独立流中的数据,所以需要以某种方式组合流。下面是一个示例示例:

this.annotationService.getWordUpdateListener().pipe(
  switchMap(thewords => {
    return this.postsService.getPostUpdateListener().pipe(
      map(posts => ({ thewords, posts }))
    );
  }),
)
.subscribe(({ thewords, posts }) => {
  this.complexWordIdentification(posts, thewords);
});

答案 2 :(得分:0)

如果同时需要this.postIWant,this.theHardWords组件初始化,则可以使用角度解析,即https://angular.io/api/router/Resolve

示例:-

class Backend {
  fetchTeam(id: string) {
    return 'someTeam';
  }
}

@Injectable()
class TeamResolver implements Resolve<Team> {
  constructor(private backend: Backend) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<any>|Promise<any>|any {
    return this.backend.fetchTeam(route.params.id);
  }
}

@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path: 'team/:id',
        component: TeamCmp,
        resolve: {
          team: TeamResolver
        }
      }
    ])
  ],
  providers: [TeamResolver]
})
class AppModule {}