【问题标题】:What is happening inside of this subscribe method in Angular Tour of Heroes?在 Angular Tour of Heroes 中这个订阅方法内部发生了什么?
【发布时间】:2019-06-07 07:27:50
【问题描述】:

我无法解决这个 .subscribe 方法内部发生的事情。

 getHeroes(): void {
    this.heroService.getHeroes()
        .subscribe(heroes => this.heroes = heroes);
  }

我一直认为this.heroes = heroes 被分配给了英雄组件内部的heroes:Hero[]。事实证明,事实并非如此。如果我将heroes:Hero[] 更改为heroes:boolean,或者即使我从英雄组件中完全删除heroes:Hero[]我的英雄仍然会显示。 this.heroes 仍然被分配。

谁能解释一下这是怎么回事?

Here is the live example

尝试执行我提到的操作并删除 heroes:Hero[] 并注意英雄仍然如何显示。如果this.heroes = heroes 没有分配给heroes:Hero[],那么订阅方法内部到底发生了什么?

【问题讨论】:

  • 它将你从服务中获得的英雄分配给类的英雄属性。 heroes: Hero[] 纯粹是 TypeScript,它在运行时不存在。 JavaScript 不关心您是否分配给任意属性,或者您是否分配“正确”的类型; 这就是 TypeScript 存在的原因
  • 内部HeroesComponent this.heroes 代表来自HeroesComponentheroes: Hero[]。在getHeroes 方法中,您从HeroService 获取所有英雄,然后通过this.heroes = heroes 将结果分配给组件的英雄列表。
  • 你的,this.heroes = heroes 是否有可能没有从 hero 组件中分配给英雄列表,而是将自己分配给 (heroes) 的方法参数,然后显示它的 observable从方法参数中的 hero.service 中检索到?
  • @jonrsharpe,如果 TypeScript 会被简单地溢出,这难道不会违背它的目的吗?我不明白为什么在这种情况下它会溢出,但在许多其他情况下,如果所有类型都不匹配,打字稿将不允许我编译。

标签: javascript angular typescript subscribe


【解决方案1】:

如果您删除heroes 属性,在从服务获取数据时,它会自动在Javascript 中创建一个属性并显示它。浏览器运行 Javascript 代码,所以没有错误。如果不声明属性或属性的数据类型不正确,则会出现 TypeScript 编译时错误

【讨论】:

  • 我正在使用 VS 代码删除heroes:Hero[],它仍在编译,这怎么可能?如果我将英雄分配给像 heroes:boolean 这样的布尔值,代码仍然会编译并显示我的英雄列表。 .subscribe 方法是否有可能没有分配给heroes:Hero[],而是将自己分配给该方法的参数?在这种情况下,heroes => this.heroes = heroes 正在从 hero.service 分配给函数内部的参数,并且完全忽略了` heros:Hero[] `?
  • 在VS代码中安装TSLint Extension,你会看到红色下划线。尝试通过ng build --prod 构建应用程序,你会得到错误。在浏览器中,执行 javescript 代码,所以没有错误,因为 javascipt 这些都不是问题。请阅读 javascript 和 typescript 之间的区别
  • Adrita,this.heroes = heroes 是否有可能没有从英雄组件中分配给英雄列表,而是将自己分配给 (heroes) 的方法参数,然后显示它的 observable从方法参数中的 hero.service 检索?如果是这样的话,英雄组件中就不需要heroes:Hero[]
  • 不,@Ne0,这里不会发生这种情况
【解决方案2】:

我一直以为 this.heroes = heros 被分配给 heros:Hero[] 里面的 heros 组件

没错。 问题是,红色下划线的错误是 TypeScript 错误。如果 TS 编译器以某种方式绕过它们并无论如何构建项目,那么 JavaScript 就没有问题,例如,动态创建一个新的对象属性。

不过,生产构建应该会失败。

【讨论】:

  • 我正在使用 VS 代码删除heroes:Hero[],它仍在编译,这怎么可能?如果我将英雄分配给像 heroes:boolean 这样的布尔值,代码仍然会编译并显示我的英雄列表。 .subscribe 方法是否有可能没有分配给heroes:Hero[],而是将自己分配给该方法的参数?在这种情况下,heroes => this.heroes = heroes 正在从 hero.service 分配给函数内部的参数,并且完全忽略了` heros:Hero[] `?
  • 没有。首先,观察者是一个箭头函数,它没有自己的this,它接受词法this,所以它的thisHeroesComponent。其次,视图仍然显示英雄列表,不是吗?它从HeroesComponent.heroes 属性中获取英雄。
  • 如果你把英雄组件中的heroes:Hero[]改成heroes:booleanthis.heroes = heroes还是被分配了?您可以在 stackblitz 的实时示例中尝试它,它仍然可以工作。这怎么可能?
  • 问和回答。
【解决方案3】:

这里 this.heroes = heroes 这里 this.heores 是顶部分配的空变量,用于保存从订阅者(英雄)获取的数据。如果你没有分配空变量,在使用 this.heores 时会报错。会抛出错误,例如“HeroesComponent”类型上不存在“属性“英雄”

【讨论】:

    【解决方案4】:

    当您删除 heroes: Hero[]; 时,它仍会显示,因为它全部从 TypeScript 编译为 JavaScript。

    为了在一个更简单的示例中轻松地对此进行可视化,它与以下非常相似,添加到对象而不首先分配它。

    var exampleObj = {};
    
    exampleObj.heroes = 'batman';
    
    console.log(exampleObj);

    这在 JavaScript 中很好,这就是为什么你的列表仍然显示,但是这不是有效的 TypeScript,会导致编译错误。

    如果我将 heros:Hero[] 更改为 heros:boolean 或者即使我从英雄组件中完全删除了 hero:Hero[],我的英雄仍然会显示。并且 this.heroes 仍然被分配。

    这意味着它会显示,因为它会在您从订阅中定义后立即添加到类中。

    有效的 JavaScript,是的。

    有效的 TypeScript,否。


    This documentation 可能有助于突出一些差异

    【讨论】:

      猜你喜欢
      • 2020-10-20
      • 1970-01-01
      • 1970-01-01
      • 2016-03-25
      • 2017-05-08
      • 2018-12-25
      • 1970-01-01
      • 2022-11-21
      • 2018-06-04
      相关资源
      最近更新 更多