【问题标题】:How to correctly return a void Observable?如何正确返回一个 void Observable?
【发布时间】:2018-04-17 16:28:07
【问题描述】:

在我的 Angular 4 应用程序中,我有一个必须返回 Observable 的方法。该方法有3个条件。第一个和第二个条件进行 get 调用,但第三个条件什么也不做,在这种情况下,我还必须返回一个 Observable,因为此方法是 .flatmap 运算符的第一部分。所以要链接.flatmap 运算符的第二部分,我需要第一部分的Observable

我尝试过return new Observable<void>();,但出现错误:

错误类型错误:无法读取未定义的属性“订阅”

这是调用服务加载数据的初始方法。

loadModelData() {
      this.customerService.getModelDetail(this.code)
        .subscribe(response => {
          this.selected = response.body as Customer;
        });
    }
  }

这是必须链接 2 个调用的服务方法。

getModelDetail(code) {

    const params = new HttpParams().set('projection', 'withBalance');

    return this.endPointUrlService.loadMaps(this.entityLink)

      .flatMap((res) => {
        return this.http.get(this.endPointUrlService.cutLinks(
          this.endPointUrlService.map.get('customers')) + '/' + code, {observe: 'response', params: params})
          .map((response) => <any>response);
      })
  }

这是来自支持服务的方法。 checkIfMapIsReady() 是在第三种情况下返回void Observable 的方法:

  loadMaps(entityLink: EntityLink[]): Observable<void> {
    console.log(entityLink);

    for (const i in entityLink) {
      if (entityLink.hasOwnProperty(i)) {
      return this.checkIfMapIsReady(entityLink[i].name, entityLink[i].searchMap, entityLink[i].endPoints[0])
      }
    }
  }


  public checkIfMapIsReady(modelName: string, mapName: string, endPoints: string) {

    if (this.map.get(modelName) === undefined) {
      console.log('endpoint url service All maps undefined ' + modelName);
      return this.getLinks(modelName, this.mapNames.get(mapName), false)
    } else {
      console.log('endpoint url service Populate only ' + mapName);
      if (this.mapNames.get(mapName).get(endPoints) === undefined) {
      return  this.getLinks(modelName, this.mapNames.get(mapName), true)
      } else {
        return new Observable<void>();
      }
    }
  }

【问题讨论】:

标签: angular rxjs


【解决方案1】:

return of(); 不创建流。

return of(void 0);

会。

如果你在模拟并且需要返回void 的流。就像我的生活一样。 [悲伤的熊猫]

【讨论】:

    【解决方案2】:

    Observable&lt;void&gt; 类型匹配的可观察对象是

    Observable.of();
    

    它导致完全 observable 没有值,类似于Observable.empty()

    虽然

    new Observable<void>();
    

    不正确,因为它缺少订阅函数参数。也可以是:

    new Observable<void>(observer => observer.complete());
    

    【讨论】:

    • 如果我返回一个未定义的值,我的平面地图或订阅有问题吗?
    • 帖子直接回答了这个问题。这就是 void observable 返回的方式。你可能会遇到 flatMap 的问题,但这意味着 Observable&lt;void&gt; 类型是错误的。它应该完成的方式取决于 getModelDetail 在您的情况下应该如何工作。可以是return Observable.empty() 或其他。
    • Observable.of() 不会发出一个未定义的,它不会发出任何东西。为此你想要Observable.of(undefined)
    • @EstusFlask 提出的解决方案都不起作用,Richard 请考虑编写您自己的答案。
    • @JacopoLanzoni 它有效。如果它没有按您的预期工作,这意味着您的期望与答案所暗示的不同。如前所述,Observable.of() 和 Observable.of(undefined) 是不同的东西。
    【解决方案3】:

    你也可以试试:

    return of(null);
    

    【讨论】:

    • 我可以确认这在我的测试中与return of(void) 的效果相同,感谢*thumbs_up
    【解决方案4】:

    也许Observable.empty() 是一个更好的选择,因为它不发出任何值,下游操作员不会对它返回的内容有任何问题!

    注意,下游flatMap(res =&gt; ...)subscribe() 不会触发。
    既然你没有使用res,我想这是想要的效果?

    为了更好的衡量,将返回类型设为Observable&lt;any&gt;

    认为下面这个在逻辑上等同于发布的checkIfMapIsReady()

    public checkIfMapIsReady(modelName: string, mapName: string, endPoints: string) {
    
      const map = this.map.get(modelName);
      const name = this.mapNames.get(mapName);
      const endPointCheck = name ? name.get(endPoints) : null;
    
      const links = !endPointCheck 
        ? this.getLinks(modelName, name, !!map)     // !! gives boolean true or false
        : Observable.empty();
    
      const msg = !map 
        ? 'endpoint url service All maps undefined ' + modelName
        : 'endpoint url service Populate only ' + mapName
      console.log(msg);    
    
      return links;
    );
    

    【讨论】:

    • 如果我在我的代码中返回 Observable.empty() 而不是 Observable&lt;void&gt;() 我有 The type argument for type parameter 'T' canno t be inferred from the usage. Consider specifying the type arguments explicitly. Type argument candidate 'void' is not a valid type argument because it is not a supertype of candidate '{}'.
    • 为了更好的衡量,将返回类型设为 Observable。 - 这是指方法签名中的返回类型。使用 'any' 作为类型会阻止 Typescript 抱怨该类型,这在您可能想要返回两种类型之一(如您所愿)时很有用。
    • 我注意到您没有使用传递给flatMapres 参数。如果确实如此,您可以考虑将返回更改为Observable&lt;boolean&gt;(进行适当的逻辑更改),而不是返回链接或 Observable
    • 是您最后的评论,我建议您更改其他 Observable&lt;void&gt;Observable&lt;any&gt;。如果您已经更改了它们两者,我们深表歉意。
    【解决方案5】:

    对于 RxJS 6.x,你需要像这样导入它:

    import { of } from 'rxjs';

    然后就使用

    return of();

    如您所见:不带任何参数意味着匹配 Observable&lt;void&gt; 的 observable。

    【讨论】:

      【解决方案6】:

      你可以使用 bahaviour observables。它们有一个初始值,当您订阅它们时,订阅会使用该初始值。所以假设如果第三个条件为真,您想对 Customer 的一个新实例进行操作,那么您可以这样做:

      `

      let customer = new Customer();
      let subj = new BehaviorSubject<Customer>(customer);
      ....
      if(thirdcondition){
        return subj;
      }
      

      `

      所以现在当你在这个方法上调用 subscribe() 并执行最后一个块时,你就得到了你想要的。 默认情况下,您可以将new customer() 更改为您想要的任何内容。

      【讨论】:

      • 但是BehaviourSubject 永远不会完成,不是吗?这不会造成悬空/丢失的订阅吗?
      • 我已经好几年没有写 Angular 代码了。对不起,我不记得了
      猜你喜欢
      • 2020-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-05
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 2017-03-28
      相关资源
      最近更新 更多