【问题标题】:Singleton class not working with component navigation单例类不适用于组件导航
【发布时间】:2019-06-18 01:58:52
【问题描述】:

我正在尝试创建一个单例类,这样我就可以避免再次打开同一个数据库。

我读过关于使用静态变量创建类提供程序以使其保持不变,但我发现每次导航到另一个组件时,静态变量内容都会丢失。

到目前为止,这是我的代码 couchbase.service.ts

import { Injectable } from "@angular/core";
import { Couchbase } from "nativescript-couchbase";
import * as connection from "tns-core-modules/connectivity";
import { isAndroid } from "platform";

@Injectable()
export class CouchbaseService {
    private static database: any;

    constructor() {
        console.log("enter constructor")
    }

    public static init(){
        if(!CouchbaseService.database) {
            console.log("enter init")
            CouchbaseService.database = new Couchbase("data");
        }
        return CouchbaseService.database;
    }

    public getDatabase() {
        return CouchbaseService.database;
    }
    ...

}

app.component.ts:我读过从这个父类调用init 会使应用程序为子类保留它(请注意,我还尝试将CouchbaseService 作为构造函数参数传递,更改方法@987654326 @转非静态)

import { Component } from "@angular/core";
import * as Platform from "platform";
import { CouchbaseService } from './services/couchbase.service';

@Component({
    selector: "ns-app",
    templateUrl: "app.component.html",
})

export class AppComponent { 
    constructor() {
        CouchbaseService.init();
    }
}

在我的app.module.ts 文件中,我将CouchbaseService 添加到providers 列表中。

import { NgModule, ErrorHandler, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptUIListViewModule } from "nativescript-ui-listview/angular";
import { NativeScriptUISideDrawerModule } from "nativescript-ui-sidedrawer/angular";
import { NativeScriptHttpModule } from "nativescript-angular/http";
import { Http } from "@angular/http";
import { NativeScriptUIDataFormModule } from "nativescript-ui-dataform/angular";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { registerElement } from 'nativescript-angular/element-registry';
import { CardView } from 'nativescript-cardview';
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";

import { CouchbaseService } from "./services/couchbase.service";


import { HomeComponent } from "./components/home/home.component";
registerElement('CardView', () => CardView);
registerElement("MapboxView", () => require("nativescript-mapbox").MapboxView);
registerElement("Fab", () => require("nativescript-floatingactionbutton").Fab);

@NgModule({
    bootstrap: [
        AppComponent
    ],
    imports: [
        NativeScriptModule,
        NativeScriptUIListViewModule,
        NativeScriptUISideDrawerModule,
        AppRoutingModule,
        NativeScriptUIDataFormModule,
        NativeScriptFormsModule,
        NativeScriptHttpModule
    ],
    declarations: [
        AppComponent,
        HomeComponent
    ],
    providers: [
        CouchbaseService,
    ],
    schemas: [
        NO_ERRORS_SCHEMA
    ],
    entryComponents: [
    ],
})
/*
Pass your application module to the bootstrapModule function located in main.ts to start your app
*/
export class AppModule { }

当我查看终端中的日志时,似乎每次我导航到另一个组件时服务都会重新启动,因此它会丢失 database 的值。

我将 NativeScript 4 与 Angular 5 和 TypeScript 2.7.2 一起使用。

【问题讨论】:

  • @Injectable({ providedIn: 'root' }) 将在应用程序的根目录创建一次服务。注入的每个地方都会收到相同的实例。
  • @JasonWhite @Injectable({ providedIn: 'root' }) 是在 Angular 6 中引入的。用户正在使用 Angular 5。

标签: nativescript nativescript-angular


【解决方案1】:

这不是应该如何使用单例服务。让我们这样做:

像这样改变你的服务:

import { Injectable } from "@angular/core";
import { Couchbase } from "nativescript-couchbase";
import * as connection from "tns-core-modules/connectivity";
import { isAndroid } from "platform";

@Injectable()
export class CouchbaseService {

    private database: any;

    constructor() {
        console.log("enter constructor")
        this.init();
    }

    private init(){
        if(!this.database) {
            console.log("enter init")
            this.database = new Couchbase("data");
        }
    }

    public getDatabase() {
        return this.database;
    }
    ...

}

在您的 AppModule [或您拥有服务的模块] 中,在 @NgModule 的提供程序数组中指定服务,如下所示:

@NgModule({
  declarations: [
    AppComponent,
    YourComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [CouchbaseService],
  bootstrap: [AppComponent]
})
export class AppModule { }

现在在您的组件中使用构造函数依赖注入,如下所示:

import { Component } from "@angular/core";
import * as Platform from "platform";
import { CouchbaseService } from './services/couchbase.service';

@Component({
    selector: "ns-app",
    templateUrl: "app.component.html",
})

export class AppComponent { 
    constructor(private service: CouchbaseService) {
        console.log(this.service.getDatabase());
    }
}

【讨论】:

  • 在检查单例服务之前,我有一个类似的代码。我能看到的唯一区别是BrowserModule 的用法,这是我需要的吗?因为我仍然失去了database 的价值
  • 添加 BrowserModule 后,我得到了这个:**ERROR** ReferenceError: Event is not defined JS: bootstrap: ERROR BOOTSTRAPPING ANGULAR JS: bootstrap: Event is not defined JS: JS: ReferenceError: Event is not defined。我正在用模块编辑我的问题,以防你需要它。这里的问题是:如果这真的是一个单例类,为什么终端总是打印enter init?这意味着它没有保存值(如果我打印它,结果是undefined
  • 我不确定您的设置可能存在什么问题。但它在我的环境中运行良好。事实上,在 stackblitaz 项目中也是如此。查看演示 - stackblitz.com/edit/angular-5-tutorial-ptzdxw?file=app/…
  • @amlibtest 不要试图复制粘贴整个代码,我建议您理解并将其应用到您的项目中。在使用 NativeScript 时,您使用 NativeScriptModule 而不是 BrowserModule,因为您的应用程序不会在浏览器中运行。这应该在 NativeScript Angular 的入门指南中有所介绍。答案是将您的服务标记为应用程序模块(根)上的提供者,因此只会创建一个实例,并且它应该在整个应用程序中都可用。
  • 我认为在将 Angular 用于您的项目之前,您必须花时间学习 Angular 的基础知识。您完全错过了关于构造函数中的依赖注入和创建自己的实例的所有内容,这就是这里的问题。另请记住,您不能使用 Angular 代码或将服务实例传递给工作线程,这是一个限制。
猜你喜欢
  • 2019-08-22
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
相关资源
最近更新 更多