Angular2:等待服务初始化

时间:2016-04-06 20:39:10

标签: angular

有没有办法在服务初始化加载其他组件之前等待? 我需要在显示组件(需要数据)之前同步加载一些数据,我不想使用promises / observables(使用那些用于异步调用)

ngIf似乎没有削减它(组件加载即使如果不匹配)。

我没有使用路由器(不需要它用于应用程序),所以我不认为@CanActivate在这种情况下是合适的。

有什么想法吗?

@Component({
    selector: 'my-app',
    directives: [MyDirective],
    template: `
    <div>
        <div *ngIf="!initialized">Loading...</div>
        <div *ngIf="initialized"><myDirective>should wait for service to be initialized</myDirective></div>
    </div>`
})
export class AppComponent {
    initialized = false;

    constructor(_myService: MyService) {
        this._myService = _myService;
    }

    ngOnInit() {
        this._myService.init()
            .then(() => {
                setTimeout( () => this.initialized = true, 2000);
            }
        );
    }
}

3 个答案:

答案 0 :(得分:2)

我不确定我是否正确理解了这个问题,但是从我得到的结果来看,我认为你可以创建一个带有初始值的模型实例(占位符),并允许你的组件使用这个模型初始化,然后,当您的数据准备就绪,更改模型实例值,这将反映到您的组件。

这样,您的组件不需要等待,它只是使用占位符数据,您当然可以在组件内部进行测试,并相应地显示您的模板,以及何时从父级准备好数据,更新它,将更新孩子。

我希望这会有所帮助。

答案 1 :(得分:1)

您使用的是什么版本的Angular?不确定您是否复制了经过修改的代码,但似乎您错过了类中的implements关键字。

*ngIf在此plunker中效果很好。

从我收集的内容来看,像@ ngIf这样的东西是在Ng2中做事的正确方法。基本上,只有在条件好的情况下才显示组件。

您可能会陷入困境,因为您的组件在您预期之前会实例化 - 因为您需要在父组件中使用它。

这可能是因为您的组件本身(或模板)需要一些值,但它们不存在(因此您的constructor会崩溃)。

根据Lifecycle Hooks上的angular.io页面,这正是OnInit界面的用途。

这是直接来自plunker的代码(你的是SubComponent):

import {Component, OnInit} from 'angular2/core'

@Component({
  selector: 'sub-component',
  template: '<p>Subcomponent is alive!</p>'
})
class SubComponent {}


@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>Hello {{name}}</h2>

      <div *ngIf="initialized">
        Initialized
        <sub-component>Sub</sub-component>
      </div>
      <div *ngIf="!initialized">Not initialized</div>
    </div>
  `,
  directives: [SubComponent]
})
export class App implements OnInit {
  initialized = false;
  constructor() {
    this.name = 'Angular2'

  }
  ngOnInit() {

    setTimeout(() => {
      this.initialized = true;
    }, 2000)
  }
}

答案 2 :(得分:0)

我通常做的是在我的数据服务中创建EventEmitter,然后在执行任何操作之前允许每个组件监听dataLoaded事件。它可能不是解决这个问题的最有效和“教科书”方式,但效果很好。例如,在app.component.ts(我最父的组件)中,我在ngOnInit挂钩中加载数据。首先,让我们看看我们的数据服务:

data.service.ts

@Injectable()
export class DataService {

dataLoaded = new EventEmitter<any>();
prop1: string;
prop2: string;

constructor(private http: HttpClient) {}

  // Asynchronously returns some initialization data
  loadAllData () {
    return this.http.get<string>('/api/some-path');
  }

}

app.component.ts

export class AppComponent {

  constructor (private dataService: DataService) {
  }

  ngOnInit() {
    this.dataService.loadAllData().subscribe((data) => {
      // Maybe you want to set a few props in the data service
      this.dataService.prop1 = data.prop1;
      this.dataService.prop2 = data.prop2;

      // Now, emit the event that the data has been loaded
      this.dataService.dataLoaded.emit();
    });
  }
}

现在我们在主应用程序组件中加载DataService并发出“已加载”事件,我们可以在子组件中订阅此事件:

@Component({
  selector: 'child-component',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

   constructor(private dataService: DataService) { 
      this.dataService.dataLoaded.subscribe(() => {
        // Once here, we know data has been loaded and we can do things dependent on that data
        this.methodThatRequiresData();
      });
   }

   methodThatRequiresData () {
      console.log(this.dataService.prop1);
   }
}