【问题标题】:DowngradeModule and downgradeInjectable result in singleton service per module in Angular/AngularJS hybrid app instead of global singletonDowngradeModule 和 downgradeInjectable 导致 Angular/AngularJS 混合应用程序中每个模块的单例服务,而不是全局单例
【发布时间】:2020-11-06 00:30:36
【问题描述】:

情况:

我正在开发一个以 AngularJS 为核心的混合项目,其中应用程序需要慢慢升级到 Angular 9。因此必须降级新的 Angular 模块才能访问 AngularJS。 AngularJS 应用程序由多个模块和子模块组成。这里只是 core(shared) 模块和 app.module 来简化:

core.ng2.module.ts

@NgModule({
    imports: [
        CommonModule
    ],
    declarations: [
        ModuleBootstrapComponent
    ],
    entryComponents: [
        ModuleBootstrapComponent
    ]
})
export class CoreNg2Module {

    constructor() {
    }

    public ngDoBootstrap(): void {
    }
}

let rootInjectorPromise: Promise<Injector>| null = null;
const getRootInjector = (extraProviders: StaticProvider[]) => {
    if (!rootInjectorPromise) {
        rootInjectorPromise = platformBrowserDynamic(extraProviders)
            .bootstrapModule(AppNg2Module)
            .then(moduleRef => moduleRef.injector);
    }
    return rootInjectorPromise;
};

const bootstrapCoreFn = async (extraProviders: StaticProvider[]) => {
    const rootInjector = await getRootInjector(extraProviders);
    const moduleFactory = await rootInjector.get(Compiler).compileModuleAsync(CoreNg2Module);
    return moduleFactory.create(rootInjector);
};

const downgradedCoreNg2Module = downgradeModule(bootstrapCoreFn);

export const coreNg2ModuleName =
    angular
        .module('core.ng2', [
            downgradedCoreNg2Module
        ])
        .directive('moduleBootstrap',
            downgradeComponent({
                component: ModuleBootstrapComponent,
                downgradedModule: downgradedCoreNg2Module
            }))
        .name;

app.module.ts

@NgModule({
    imports: [
        BrowserModule,
        CommonModule,
        CoreNg2Module,
    ]
})
export class AppNg2Module {

    constructor() {
    }

    public ngDoBootstrap(): void {
        // Don't use this lifecycle hook since the hybrid app is bootstrapped manually inside Bootstrap.ts.
    }
}


export const appModuleName = angular
    .module('app.ng2', [
        coreNg2ModuleName,
    ]).factory('translateSyncService',
        downgradeInjectable(TranslateSyncService))
    .name;

目前的问题:

我根据官方指南降级并引导模块:https://angular.io/api/upgrade/static/downgradeModule#downgrading-multiple-modules 让我的 app.module 作为我的 TranslateSyncService 的“根”。因为根据这个https://angular.io/guide/upgrade#how-ngupgrade-works单例服务在AngularJS和Angular IF之间共享,它们是在“根”中提供的。 我需要 translate-sync-service 来将 Angular 组件的状态与 AngularJS 应用程序同步。

@Injectable({
    providedIn: 'root'
})
export class TranslateSyncService {

    languageSource = new BehaviorSubject<string>('en');
    usedLanguage$ = this.languageSource.asObservable();

    constructor() {
    }


    changeLanguage(language: string) {
        this.languageSource.next(language);
    }
}

我降级了模块和服务,使其可以在 AngularJS 中访问。问题是服务正在工作,但每个模块都有自己的服务实例,而不是全局单例服务。所以核心模块有自己的服务和我创建的每个其他模块。

tldr;我最终得到了每个模块的单例服务,而不是全局服务。

我的愿望: 我想要一个 Angular 服务,它是跨降级的 Angular 模块和 AngularJS 应用程序的单例。

有没有人遇到过这个问题?

【问题讨论】:

    标签: angularjs angular singleton injectable


    【解决方案1】:

    我知道这很旧,但我遇到了同样的问题。我找到了一个对我有用的答案(类似情况)。我们使用我们注入到 Angular JS 应用程序中的降级模块的通用模式。 (其他地方有很多这样的例子)。

    export const downgradedAngularAppModule = angular.module('downgraded-angular-module', [downgradedAngularModule])
                                                     .service('SomeAngularXService', downgradeInjectable(SomeAngularXService))
    

    然后在 angularJS 中

    export const angularJsModule: ng.IModule = angular.module(angularjsAppModule, [list of angularJS modules, downgradedAngularAppModule.name])
    

    虽然仍处于混合模式,但我们在 Angular JS 中引导 Angular。在单例 angular X 服务中,确保您使用以下内容进行装饰:

    @Injectable(
        { providedIn: 'root' } // this means app wide singleton
    )
    

    如果您希望在您的 angularJS 应用程序中使用相同的服务实例,在您已迁移到 angular X 的组件中,而不是导入模块直接这样:

    import { SomeAngularXService } from 'SomeAngularXService.service.ts'
    

    并在你的构造函数中注入它:

    constructor(private someAngularXService: SomeAngularXService)
    

    你应该在你的构造函数中使用 angularJS 实例

    constructor(@Inject('SomeAngularXService') private someAngularXService: any)
    

    你需要记住在你的 app.module.ts 中提供它

    {
        provide: 'SomeAngularXService',
        useFactory: ($injector: any) => $injector.get('SomeAngularXService'),
        deps: ['$injector']
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 2021-09-13
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      • 2019-12-27
      相关资源
      最近更新 更多