angularjs - DowngradeModule 和 downgradeInjectable 导致 Angular/AngularJS 混合应用程序中每个模块的单例服务,而不是全局单例
问题描述
情况:
我正在开发一个以 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 之间共享,如果它们在“根”中提供。我需要 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 应用程序的单例。
有人有这个问题的经验吗?
解决方案
我知道这很旧,但我遇到了同样的问题。我找到了一个对我有用的答案(类似情况)。我们使用我们注入到 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']
}
推荐阅读
- java - 如何在视图中显示对话框?
- python - 使用正则表达式在不同列的熊猫数据框中查找单词并创建新值
- google-apps-script - 如果列公式值在谷歌脚本中更改为 TRUE,则脚本复制行
- json - 在 mule 4 中允许 excel 表的空单元格值
- java - 如何挤压一个数组,使没有连续的两个或多个值出现并被那个值替换
- apache - 重定向和屏蔽 URL,但保留查询参数(Apache 或 htaccess)
- c++ - C++ 访问静态 constexpr 数组
- javascript - 为什么没有在反应js中选中复选框?
- javascript - 异步功能完成后如何停止终端运行
- c# - 时间序列的图表垂直网格设置