【问题标题】:Observable returned by service won't complete服务返回的 Observable 不会完成
【发布时间】:2018-02-07 00:18:22
【问题描述】:

我有一个使用 Angular 的 http 服务的服务

@Injectable()
export class MyService {

  constructor(private http: Http) { }

  getThings() {
    return this.http.get('url').map((res) => {
      // massage data here and return massaged data
    });
  }
}

我使用这样的服务

this.myService.getThings.subscribe(
  things => {},
  err => {},
  () => {
    // never completes...
  });

虽然http.get('url') 完成了,但为什么myService.getThings() 从未完成?

我怎样才能使myService.getThings() 完整?

【问题讨论】:

  • 这对你来说可能很有趣:github.com/angular/angular/issues/7865
  • 你解决了这个问题吗?
  • 我使用finally方法
  • 考虑选择一个答案,以便您的问题被标记为已解决

标签: angular rxjs rxjs5 angular2-http


【解决方案1】:

http.get('url') 没有“完成”,因为它所做的只是映射从您的服务器发送的响应。

关于 Observables 有一点需要注意:在订阅之前,它们实际上不会做任何事情。其次,如下代码:

return this.http.get('url').map((res) => {
  // massage data here and return massaged data
});

返回一个 Observable,它只是一个返回数据流的函数。

关于 Observable 的另一点需要注意的是,并非所有的 Observable 都会固有地完成。 Observables 仅在其源完成时才完成。在这种情况下,http.get() 函数确实完成了,因此您不必担心。

最后,如果 Observables 触发错误,它们将不会完成。对于 http.get() 函数,如果服务器产生任何不是 200 级响应的响应,则会触发错误。

我建议您更改 getThings 函数以包含 catch 运算符:

import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

return this.http.get('url')
   .map((res) => {
      // massage data here and return massaged data
   })
   .catch((error: Response) => {
      return Observable.throw(error.status);
   });

如果 get() 请求发生错误,它将返回一个包含来自服务器的状态的 Observable。然后你可以看看状态,看看是什么问题。

【讨论】:

  • 根据所需的架构,您对catch 子句的建议无济于事。而不是将完整的错误对象传播到subscribe,您现在只能在onError 中获得status 字段。
【解决方案2】:

这可能是由于 websockets 或 github 问题中所述的其他机制而无法完成:https://github.com/angular/angular/issues/7865; 但是这里有两个 Angular2 和 Angular4 的 plunkr,它们都通过 HTTP 使用模拟 json 文件,并且在这两种情况下 observable 都正确完成。

在这两种情况下,我都设置了与您类似的情况:

this.toto().subscribe(
      (result) => {
        console.log('result => ', result);
      },
      (error) => {
        console.log('error => ', error);
      },
      () => {
        console.log('comlete');
      }
    });

  toto() {
    return this.http
    .get('test.json')
    .map((res) => res.json());
  }

Plunkr1:http://plnkr.co/edit/hoIyMHl8abhaG7BYVyns?p=preview

Plunkr2:http://plnkr.co/edit/siVrOIIvT1uWP36LkiOZ?p=preview

【讨论】:

    【解决方案3】:

    如果过程中发生错误,则不会执行“完成”块。 (不能作为 finally)。

    在所有步骤中添加一些日志以查找是否发生了错误。

    【讨论】:

      【解决方案4】:

      我建议您使用 finally 运算符,以防您想在流发出其最后一个值(完成)时执行代码。

      例如:

      //Inside of a component
      this.fooService.getFoos().
      finally(()=>console.log("Completed"))
      .subscribe(foos => this.foos = foos);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-18
        • 1970-01-01
        • 2016-09-15
        • 2020-02-12
        • 2021-08-25
        • 1970-01-01
        • 2020-07-14
        • 2017-04-17
        相关资源
        最近更新 更多