如何在Ionic 2中使用Angular 2服务?

32

我是 Ionic 2 的新手。 我在 Angular 2 文档中读到,服务需要在引导应用程序时注入。 但是在学习 Ionic 2 教程时没有看到任何引导内容。

非常感谢您的帮助。

3个回答

36
在Ionic2中没有使用Bootstrap()的必要,只需使用@App来声明您的应用程序。 您仍然需要在@Page组件中声明您的服务。 创建您的服务。
import {Injectable} from "angular2/core";
import {Http} from "angular2/http";

@Injectable()
export class DataService {
  constructor(http: Http) {
    this.http = http;
    this.data = null;
  }

  retrieveData() {
    this.http.get('./mocks/test.json')
    .subscribe(data => {
      this.data = data;
    });
  }

  getData() {
    return this.data;
  }
}

然后在你的@Page中使用它

import {Page} from 'ionic/ionic';
import {DataService} from './service';

@Page({
  templateUrl: 'build/test.html',
  providers: [DataService]
})
export class TestPage {
  constructor(data: DataService) {
    data.retrieveData()
  }
}

8
您可以通过将该服务添加到@App提供程序数组中,并且不要将该服务添加到所述@Page的提供程序中,以实现与Bootstrap类似的功能。 - Boštjan Pišler
1
是的,但最好的做法是在使用服务时指定它们。 - Raphael
一个服务必须是整个应用程序的单例,以共享诸如缓存之类的公共数据,这意味着它必须在顶级组件中定义。如果我们谈论像服务这样的模型,那么就是这样。另一方面,像http这样的其他服务则不需要彼此了解。 - Boštjan Pišler
4
在需要使用服务时进行注入并不是最好的实践,这会创建一个单独的实例,通常不是服务的预期行为。一般来说,您希望有一个单一的实例,只在@App中进行注入。在您的示例中,两个不同的页面将拥有各自关联的实例,因此在page1中调用retrieveData(),并尝试在page2中使用getData()将不会返回刚刚检索到的数据。 - Manu Valdés
我遇到了一个问题,当我在其他文件夹中使用 getData() 函数时,会出现问题,因为从 API 返回的响应需要时间,那么我该如何解决这个问题? - Anuj
显示剩余5条评论

24

RC更新:

从Ionic2 RC版本开始,现在服务应该包含在@NgModuleproviders数组中,以使这些服务作为单例工作(意味着整个应用程序将使用同一个实例)。

@NgModule({
  declarations: [
    MyApp,

    // Pages
    Page1,
    Page2,

    // Pipes
    MyCustomPipe,

    // Directives
    MyCustomDirective,
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,

    // Pages
    Page1,
    Page2
  ],
  providers: [ DataService, NavigationService, Storage, ... ] // <- here!
})
export class AppModule {}

旧回答(2.0.0-beta.8)

以防这对其他 Ionic2 开发者有所帮助,从 2.0.0-beta.8 版本开始,现在我们可以使用 ionicBootstrap 来使我们的服务作为单例(即整个应用程序中将使用同一实例)。

需要进行的更改很少;您的服务将保持不变。

/* Notice that the imports have slightly changed*/
import {Injectable} from "@angular/core";
import {Http} from "@angular/http";
import 'rxjs/Rx';

@Injectable()
export class DataService {
  constructor(http: Http) {
    this.http = http;
    this.data = null;
  }

  retrieveData() {
    this.http.get('./mocks/test.json')
    .subscribe(data => {
      this.data = data;
    });
  }

  getData() {
    return this.data;
  }
}

但是,不要将其作为provider注入到您的Component中(这将导致每次加载component时都创建一个新实例的service

import {Component} from '@angular/core';
import {DataService} from './service';

@Component({
  templateUrl: 'build/test.html'
  /* This should not be done anymore */
  /* providers: [DataService] */
})
export class TestPage {
  constructor(data: DataService) {
    data.retrieveData()
  }
}

将其包含在app.ts文件的ionicBootstrap中,以确保整个应用程序使用同一实例的服务。

ionicBootstrap(MyApp, [DataService], {});

Angular风格指南:

遵循Angular2 Style Guide

在顶层组件中向Angular 2注入器提供服务,这样它们就可以被共享。

为什么? Angular 2注入器是分层的。

为什么?将服务提供给顶级组件时,该实例将被共享并可用于该顶级组件的所有子组件。

为什么?当服务共享方法或状态时,这是理想的情况。

它能工作。只是不是最佳实践。引导提供程序选项旨在配置和覆盖Angular自己预注册的服务,例如其路由支持。

因此,我们需要在应用程序的顶层组件中注册服务(如果我们希望在整个应用程序中使用相同的实例),而不是在ionicBootstrap中注册, 如下所示:

@Component({
  templateUrl: 'build/app.html',
  directives: [...],
  providers: [..., DataService]
})
class MyApp{ 
  // ...
} 

1
这对我解决了问题,非常感谢。不知道有没有关于这个的文档,因为一个关于 Promises 的模糊错误很难找到。 - webdevinci
Ionic团队仍在努力完善文档,但由于Ionic2是基于Angular2构建的,您可以在Angular样式指南和其他相关Angular文档页面中找到这些内容。为了了解注入器的工作原理(这使我能够理解这个主题并撰写本答案),您可以查看此页面 - sebaferreras
嗨,我尝试遵循@sebaferreras的示例。看起来服务已被选中,但每当我包含该服务时生成的屏幕是空白的。有任何想法为什么会这样吗?该服务位于src/providers/global-alerts.ts中。 - Cornelius Parkin

0

搜索Ionic提供程序,在Ionic中,我们使用Ionic Provider而不是Angular服务,它们提供了Ionic中的依赖注入概念。

生成Ionic提供程序

ionic generate provider <provider name>

然后在根页面或需要使用它的页面中导入提供程序

并将其放入提供程序数组中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接