【问题标题】:Angular subscribe. Can't get to data角订阅。无法获取数据
【发布时间】:2019-07-23 23:51:41
【问题描述】:

更新 我是如何做到的如下(滚动到我的答案或这里的链接): https://stackoverflow.com/a/55013081/1729405

我正在尝试在 Angular 7 中构建 APIService。我正在使用订阅推送到无法通过其他服务访问的数组。

api服务方法如下:

  getResponse(url):Observable<any> {
    return this.http.post(url, '', {responseType: 'text'});
  }

  getAll() {
      this.getResponse(this.todayApiUrl).subscribe(
        (response) => {
          this.data.push(response);
        });

      return this.data;
  }

这是我尝试在辅助服务中调用它的方式:

export class AdsHealthService {
  today = this.callResponseApiService.getAll();


  constructor(private callResponseApiService: CallResponseApiService) { }

  getHealthValue(interval, type) {
    let obj = this.today;
    console.log(obj);
  }
}

在我console.log() 回复时得到的图片。它看起来像一个数组,但是当我尝试访问第一个元素时,我收到了 undefined 消息。我究竟做错了什么??

【问题讨论】:

    标签: angular typescript api service


    【解决方案1】:

    发生这种情况是因为 http.post 是异步的,您可以通过使 getResponse() async 使其同步,将 Observable 转换为 Promise 通过 .toPromise() 并在 await 之前添加 @987654328 @ 因为 getResponse() 不会返回 Observable 而是原始数据,所以 .subscribe() 不再需要。

      async getResponse(url) {
        return await this.http.post(url, '', {responseType: 'text'}).toPromise();
      }
    
      async getAll() {
        this.data = await this.getResponse('some url');
        return this.data
      }
      async some() {
        const data = await this.getAll();
        console.log(data);
        console.log(this.data);
      }
    

    【讨论】:

    • 我收到了您提供的解决方案的承诺。你如何从承诺中获得价值? async getAll() { 让 promise = this.http.post(this.todayApiUrl, '', {responseType: 'text'}).toPromise(); promise.then(function(value) { return value; }); this.today = 等待承诺; console.log(this.today); // this 返回一个字符串值 return this.today;在 AdsHealthService 类中: this.data = this.callResponseApiService.getAll();控制台.log(this.data); // 这会返回一个 promise 对象而不是字符串 谢谢!
    • 我已经更新了答案。谢谢你指出。因为 getAll()async 你也必须用 await 来调用它。
    • 当在异步函数 some() 之外引用 this.data 时,我仍然无法定义。有没有办法在异步函数之外获取字符串值(因为所有异步函数都返回一个承诺)?
    • 您想对这些数据做什么,只是在 UI 中显示它们或进行一些修改?
    • 你明白了!答案如下。 :)
    【解决方案2】:

    在您的服务中,您需要以下内容:

      async getResponse(url) {
        return await this.http.post(url, '', {responseType: 'text'}).toPromise();
      }
    
      async getAll(url) {
        return await this.getResponse(url);
      }
    

    在另一个服务/组件中,您可以像下面这样检索承诺。为了确保你得到一个承诺,你需要使用一个 try catch 块。

      async getToday() {
        try {
          let today = await this.yourServiceName.getAll(this.todayApiUrl);
          return today;
        } catch(e) {
            console.log(e);
        }
      }
    

    然后调用:

    let data = this.yourServiceName.getToday();
    this.data.then((res) => {
    // do stuff with 'res' here.
    }
    

    没有办法将值保存在 then 范围之外。为了避免多次访问 API,我设置了一个缓存服务,以便您可以在必要时从缓存中存储/检索。这是我引用的缓存文章的链接:https://hackernoon.com/angular-simple-in-memory-cache-service-on-the-ui-with-rxjs-77f167387e39

    您可以这样做:

      if (!this.cacheService.has('some key')) {
        let data = this.yourServiceName.init();
        this.cacheService.set('some key', data)
      } else {
        let cache = this.cacheService.get('data');
        // do stuff here.
      }
    

    希望有帮助!

    【讨论】:

      【解决方案3】:

      您没有获取数据或数据为 null 或未定义,因为您的休息端点将来会返回数据,但您的 return 语句会立即返回。

      以下是解决此问题的方法

      • 在模板中使用async管道,在服务中使用.map
      • 使用map 在组件中准备就绪时获取数据

      下面是代码

        // one method is fine to return data from rest endpoint
        getAll(url):Observable<any> {
           return this.http.post(url, '', {responseType: 'text'});
         }
      

      在你的组件类中

      export class AdsHealthService {
      
        constructor(private callResponseApiService: CallResponseApiService) {
           this.callResponseApiService.getAll().subscribe( (today) => {
             let obj = today;
             console.log(obj);
           });
        }
      
       rawdata = this.callResponseApiService.getAll();
      
      
      }
      

      如果您直接在模板中显示数据,您可以使用async 管道来做到这一点。

      &lt;div&gt;{{rawdata | async}}&lt;/div&gt;

      【讨论】:

      • 我可以使用 Promises 来获得它。由于一些非常奇怪的原因,Observable 不会以我可以获取数据的方式返回。不知道为什么。感谢您的反馈!
      【解决方案4】:

      你可以这样做:

      在您的应用组件中:

      public getDataFromService() {
        this._api.getData(this);
      }
      
      
      public setData(data: any){
       this.data=data;
      }
      

      在您的 service.ts 中:

      public getData(obj: appComponentModel){
          this.http.get(url).subscribe(res => obj.setData(res));
      }
      

      它的格式与您的问题不完全相同,但任何人都很容易理解。

      【讨论】:

      • 首先,欢迎来到 Stack。欣赏答案。如果我回到这样的情况,我会看看你的解决方案。 :) 自从它发布以来我还没有碰过它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 2022-10-14
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多