Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 角度8如何从ngOnInit中的可观测值中获取值,以及它们的行为如何_Angular_Typescript_Http_Observable - Fatal编程技术网

Angular 角度8如何从ngOnInit中的可观测值中获取值,以及它们的行为如何

Angular 角度8如何从ngOnInit中的可观测值中获取值,以及它们的行为如何,angular,typescript,http,observable,Angular,Typescript,Http,Observable,你好社区, 我正试图使用HttpClient模块从api中获取一些数据。 api调用在我的服务中定义。我在组件的Lifecyclehooks中调用它们,但我很难理解返回的可观察对象的行为,以及如何在ngOnInit中获得它的价值 我构建了一个示例代码,用于记录返回的数据对象,以了解它们的行为。服务函数返回可观察的结果 这就是我的示例代码的样子: 我的示例服务: 从'@angular/core'导入{Injectable}; 从'@angular/common/http'导入{HttpCli

你好社区
我正试图使用HttpClient模块从api中获取一些数据。
api调用在我的服务中定义。我在组件的Lifecyclehooks中调用它们,但我很难理解返回的可观察对象的行为,以及如何在ngOnInit中获得它的价值

我构建了一个示例代码,用于记录返回的数据对象,以了解它们的行为。服务函数返回可观察的结果


这就是我的示例代码的样子:

我的示例服务:

从'@angular/core'导入{Injectable};
从'@angular/common/http'导入{HttpClient};
从“../config/config.service”导入{ConfigService};
@可注射({
providedIn:'根'
} )
导出类实验服务{
构造函数(私有http:HttpClient,私有ConfigService:ConfigService){}
private\u apiRootUrl:string=this.ConfigService.get('api\u root\u url');
private\u apiUser:string=this.ConfigService.get('api\u user');
private_apiPath:string=this.ConfigService.get('api_path');
公共交通灯(){
返回this.http.get(
`${this.\u apiRootUrl}/${this.\u apiUser}/${this.\u apiPath}`
);
}
}
我的样品成分:

从'@angular/core'导入{Component};
从“../../services/experimental/experimental.service”导入{ExperimentalService};
@组成部分({
选择器:'应用程序实验',
templateUrl:'./experimental.component.html',
styleURL:['./实验性的.component.scss']
})
导出类实验组件{
构造函数(私有实验服务:实验服务){}
私人测试1;
私人测试2;
私有执行:布尔值=false;
ngOnInit():void{
console.log(“----ngonit-----”);
此.ExperimentalService.getLights().subscribe(
(数据)=>{
this.test1=数据;
log(“Test:1.1”,this.test1);//--1.1---
}
);
log(“Test:1.2”,this.test1);//--1.2---
}
ngDoCheck():void{
console.log(“----ngDoCheck-----”);
if(this.executed==false){//if:仅用于避免无休止的循环
此.ExperimentalService.getLights().subscribe(
(数据)=>{
this.test2=数据;
log(“Test:2.1”,this.test2);//--2.1---
}
);
log(“Test:2.2”,this.test2);//--2.2---
log(“Test:1.3”,this.test1);//检查test1是否在ngOnInit之后
if(this.test2){
this.executed=true;
} 
}
}
}
控制台输出:

----- ngOnInit -----
Test: 1.2 undefined

----- ngDoCheck -----
Test: 2.2 undefined
Test: 1.3 undefined

----- ngDoCheck -----
Test: 2.2 undefined
Test: 1.3 undefined

Test: 1.1 Object { 1: {…}, 2: {…}, 3: {…} }

----- ngDoCheck ----- 
Test: 2.2 undefined 
Test: 1.3 Object { 1: {…}, 2: {…}, 3: {…} }
Test: 2.1 Object { 1: {…}, 2: {…}, 3: {…} }

----- ngDoCheck -----
Test: 2.2 Object { 1: {…}, 2: {…}, 3: {…} }
Test: 1.3 Object { 1: {…}, 2: {…}, 3: {…} }
Test: 2.1 Object { 1: {…}, 2: {…}, 3: {…} }

  • 为什么.2在.1之前被记录?
  • 为什么第一个循环返回undef?(我的想法是:Api需要很长时间才能提供响应?!)
  • 如何获得ngOnInit中的值?如果我的想法是2,是否有等待api响应的选项。是吗

  • 谢谢你的帮助

  • 这是由于JavaScript的异步特性,而可观察对象的返回是异步的

  • 是的,您正在等待答复

  • 您可以通过在
    subscribe()
    块中移动后续逻辑来获取值

  • 以下是您执行订阅的方式:

    ngOnInit(): void {
      this.ExperimentalService.getLights().subscribe(
        (data) => {
          this.test1 = data;
          console.log("Test: 1.1", this.test1); // --- 1.1 ---
          console.log("Test: 1.2", this.test1); // --- 1.2 ---
        }
      );
    } 
    
  • 这与可观察事物的异步性质有关。当您订阅observable时,函数代码将仅在HTTPGET返回值时运行

  • 因为可观察对象没有收到任何值

  • 使用async Ngonit并使用await关键字进行值检查

  • async ngOnInit():Promise{
    let heroes=等待。heroService.getHeroes();
    this.heroses=heroses.slice(1,5);
    }
    
    就你而言

    async ngOnInit(): Promise<void> {
        console.log("----- ngOnInit -----");
        this.test1  = this.ExperimentalService.getLights().subscribe();
        console.log("Test: 1.2", this.test1); // --- 1.2 ---
      }
    
    async ngOnInit():Promise{
    console.log(“----ngonit-----”);
    this.test1=this.ExperimentalService.getLights().subscribe();
    log(“Test:1.2”,this.test1);//--1.2---
    }
    
    从服务器加载数据需要更多时间。最简单的方法是使用如下条件:

    ngOnInit(): void {
        this.ExperimentalService.getLights().subscribe(
            (data) => {
                if (data) {
                    this.test1 = data;
                }
            }
        );
    }
    
    不要忘记取消订阅:

    import { Subscription } from 'rxjs';
    
    subs: Subscription[] = [];
    
    ngOnInit(): void {
        this.subs.push(this.ExperimentalService.getLights().subscribe(
            (data) => {
                if (data) {
                    this.test1 = data;
                }
            }
        ));
    }
    
    ngOnDestroy() {
        this.subs.forEach(sub => sub.unsubscribe());
    }
    

    getLights
    函数返回一个
    可观察的
    Observable
    本身不会阻止执行,它只在结果可用时保存信息。为了在结果可用时得到通知,带有回调函数的订阅将通过
    subscribe
    函数注册到可观察的上。在回调中,结果数据将出现

    如上所述,observable不会阻止代码的执行,subscribe调用也不会。这意味着:

  • 将注册一个回调,该回调将打印
    Test:1.1
    ,但尚未启动,因为http请求尚未完成。所以什么也没印出来
  • 代码执行将继续并打印
    Test:1.2
    ,结果为
    未定义
    ,因为之前的订阅未启动,因此未为
    此.test1设置值
  • 一段时间后,由于结果到达,将执行订阅回调,因此
    Test:1.1
    将打印结果
  • 如果要在注册订阅后显式阻止执行以首先检索结果,可以执行以下操作:

      async ngOnInit(): void {
        console.log("----- ngOnInit -----");
        this.test1 = await this.ExperimentalService.getLights().toPromise();
        console.log("Test: 1.2", this.test1); // --- 1.2 ---
      }
    
    注意:
    ngOnInt
    本身是可等待的,这一点很重要

    这将隐式注册将转换为承诺的订阅。承诺将保留在可观测完成后发出的最后一个值。由于Angular的Http客户机在收到值后完成返回的Observable,因此当请求成功或因错误而被拒绝时,结果承诺将得到解决

    你可以把任何可见的
      async ngOnInit(): void {
        console.log("----- ngOnInit -----");
        this.test1 = await this.ExperimentalService.getLights().toPromise();
        console.log("Test: 1.2", this.test1); // --- 1.2 ---
      }
    
      async ngOnInit(): void {
        console.log("----- ngOnInit -----");
        this.test1 = this.ExperimentalService.getLights().pipe(first()).toPromise();
        console.log("Test: 1.2", this.test1); // --- 1.2 ---
      }