【问题标题】:How wait to execute service in angular?如何等待以角度执行服务?
【发布时间】:2020-08-27 09:10:38
【问题描述】:

我有代码:

data.service.ts

  getDataById(id: number): Observable<Model> {
    return this.httpClient.get<Model>(this.api + 'data?id=' + `${id}`);
  }

data.component.ts

firstFunc(id) {
 this.secoundFunc(id);
 console.log('res from service', this.data); // log undefined
 //do something with this.data
}

secoundFunc(id) {
 this.dataService.getDataById(id).subscribe(res=> {
 this.data = res;
})
}

如何等待服务执行?然后继续执行剩下的代码。 我知道http请求是作为异步操作完成的。我用过,promises,async/await,setTimeout,但这些都没有帮助。

【问题讨论】:

  • 我用过,promises,async/await,setTimeout....可以在帖子里分享一下吗?

标签: angular http asynchronous promise async-await


【解决方案1】:

您可以对订阅中的数据进行操作。

    firstFunc(id) {
     this.secoundFunc(id);
    }
    
    secoundFunc(id) {
     this.dataService.getDataById(id).subscribe(res=> {
     this.data = res;
     console.log('res from service', this.data); 
     //do something with this.data
    })
    }

【讨论】:

  • 当然可以,但我不想在那段代码中做“某事”。
  • 正如this answer 所说:拥抱 JavaScript 的异步特性!
【解决方案2】:

没有办法将异步变量变为同步。您唯一能做的就是根据订阅中的异步变量移动所有语句。

firstFunc(id) {
  this.dataService.getDataById(id).subscribe(res=> {
    this.data = res;
    console.log('res from service', this.data);
    //do something with this.data
  });
}

如果您需要在多个地方使用this.data,并且不希望每次都触发HTTP调用,您可以使用RxJS ReplaySubject在服务中缓存响应并在组件中使用它。

服务

export class DataService {
  private cachedSource = new ReplaySubject<any>(1);      // <-- cache last emitted value
  public cached$ = this.cachedSource.asObservable();

  getDataById(id: number): Observable<Model> {
    return this.httpClient.get<Model>(this.api + 'data?id=' + `${id}`).pipe(
      tap(res => this.cachedSource.next(res))
    );
  }
}

组件

export class SampleClass implements OnDestroy {
  complete$ = new Subject<any>();

  firstFunc(id) {
    this.getDataById(id);
    this.dataService.cached$.pipe(takeUntil(this.complete$)).subscribe(
      res => {
        this.data = res;
        console.log('res from service', this.data);
        //do something with this.data
      }
    );
  }

  someOtherFunction() {
    this.dataService.cached$.pipe(take(1)).subscribe(
      res => {          // <-- will emit the last value from the HTTP call
        console.log('res from service', res);
        //do something with `res`
      }
    );
  }

  getDataById(id: number) {
    this.dataService.getDataById(id).subscribe();     // <-- pushes response to `this.dataService.cached$`
  }

  ngOnDestroy() {
    this.complete$.next();        // <-- close open subscriptions
  }
}

【讨论】:

  • 谢谢。我知道这一点,但我想知道这个问题是否可以通过其他方式解决。感谢您的回答。
  • @DraganKrivokuća:无论如何你都需要使用异步变量。如果您不希望在组件中每次使用它的响应时触发 HTTP 请求,我在答案中包含了一个基本的缓存方法。
  • 是的,这会有所帮助。但是我需要通过id来查看数据,而且每次都要触发http请求来检查是否有变化。
  • @DraganKrivokuća:在这种情况下,您可以在需要最新数据的任何地方触发 HTTP 功能。
【解决方案3】:

也许你可以试试回调!

firstFunc(id) {
 this.secoundFunc(id, () => {
   console.log('res from service', this.data); 
   //do something with this.data
 });
}

secoundFunc(id,callback) {
 this.dataService.getDataById(id).subscribe(res=> {
   this.data = res;
   callback && callback();
 })
}

或者试试异步功能

   async firstFunc(id) {
    const result = await this.secoundFunc(id).toPromise();
    // if (result ???)
    // do sth
   }
   
   secoundFunc(id) {
    return this.dataService.getDataById(id)
   }

【讨论】:

    猜你喜欢
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多