Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在angularjs/angularjs混合应用程序中结合使用降级模块和降级可注入会导致错误_Javascript_Angular_Ng Upgrade - Fatal编程技术网

Javascript 在angularjs/angularjs混合应用程序中结合使用降级模块和降级可注入会导致错误

Javascript 在angularjs/angularjs混合应用程序中结合使用降级模块和降级可注入会导致错误,javascript,angular,ng-upgrade,Javascript,Angular,Ng Upgrade,使用angular 5.0,升级模块现在可以选择使用降级模块,该模块在angularjs区域之外运行angularjs。在进行这方面的实验时,我遇到了一个使用可注射降级的问题 我收到错误信息: 未捕获错误:尝试在引导角度模块之前获取角度注入器 @NgModule({ // ...providers, imports etc. declarations: [ // ... existing declarations ServiceBootstrapComponent ]

使用angular 5.0,升级模块现在可以选择使用降级模块,该模块在angularjs区域之外运行angularjs。在进行这方面的实验时,我遇到了一个使用可注射降级的问题

我收到错误信息:

未捕获错误:尝试在引导角度模块之前获取角度注入器

@NgModule({
  // ...providers, imports etc.
  declarations: [
    // ... existing declarations
    ServiceBootstrapComponent
  ],
  entryComponents: [
    // ... existing entry components
    ServiceBootstrapComponent
  ]
})
export class MyAngularModule {}
在angular js中引导angular运行良好

import 'zone.js/dist/zone.js';
import * as angular from 'angular';
/**
 * Angular bootstrapping
 */
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { decorateModuleRef } from 'src/environment';
import { AppModule } from 'src/app/app.module';
import { downgradeModule } from '@angular/upgrade/static';

export const bootstrapFn = ( extraProviders ) => {
    const platformRef = platformBrowserDynamic( extraProviders );
    return platformRef
        .bootstrapModule( AppModule )
        .then( decorateModuleRef );
};

angular.module( 'app.bootstrap', [
    downgradeModule( bootstrapFn ),
] );
但是…

由于引导发生在angularjs初始化之后,我无法再让降级注入工作

要降级的服务

import { Injectable, Inject, OnInit } from '@angular/core';

@Injectable()
export class MobileService implements OnInit{
    constructor(
        @Inject( 'angularjsDependency1' ) public angularjsDependency1 : any,
        @Inject( 'angularjsDependency2' ) public angularjsDependency2 : any,
    ) {}

}
降级可注入尝试

import * as angular from 'angular';
import { downgradeInjectable } from '@angular/upgrade/static';
import { MyService } from 'src/services/myService/myService';

export const myServiceDowngraded = angular.module( 'services.mobileService', [
    angularjsDependency1,
    angularjsDependency2,
] )

.factory(
    'mobileService',
    downgradeInjectable( MyService ),
).name;
当“降级可注入(MyService)”运行时,由于angular尚未启动,angular injector不可用。因此出现错误:

未捕获错误:尝试在引导角度模块之前获取角度注入器

@NgModule({
  // ...providers, imports etc.
  declarations: [
    // ... existing declarations
    ServiceBootstrapComponent
  ],
  entryComponents: [
    // ... existing entry components
    ServiceBootstrapComponent
  ]
})
export class MyAngularModule {}

有人知道我该如何解决这个问题吗?

这是在一个有角度的github线程中向我指出的

乔治·卡尔帕卡斯的回答:

我想说清楚: 您可以将降级可注入()与降级模块()一起使用,但存在某些限制。特别是,在Angular启动之前,您不能尝试注入降级可注入。Angular启动(异步)第一次呈现降级组件时。因此,您只能在降级组件(即升级的AngularJS组件)内安全地使用降级服务

我知道这是一个很大的限制,你可能会决定根本不使用DegrammeInjectable()——只是想让它更清楚你能做什么和不能做什么

请注意,当使用升级的可注入UpgradeModule时,等效的限制是正确的:在AngularJS被引导之前,您不能使用它。但是,这个限制通常不会被注意到,因为AngularJS通常是在Angular模块的ngDoBootstrap()方法和AngularJS中引导的(与AngularJS不同)同步引导


我也有同样的问题,在找到这个问题之前几个小时,问题就被解决了。 我的解决方法是创建一个ServiceBootstrapComponent,它什么都不做,只注入我们需要降级的所有服务

然后我将该组件降级,在@NgModule中将其标记为en条目,并将其添加到index.html

<body>
  <service-bootstrap></service-bootstrap>
  <!-- existing body contents -->
</body>
对我来说很有用。

注意:下面的答案遵循的惯例是将Angular1.x称为angularjs,将所有Angular2+版本称为angularjs

扩展JGoodgive上面的答案,基本上,如果您使用的是
降级模块
,那么angularjs在需要渲染第一个角度组件时会延迟引导angularjs。在此之前,由于angular模块没有初始化,如果您使用
降级Injec访问angularjs内的任何角度服务表
,这些服务也不可用

解决方法是尽早强制角度模块引导。为此,需要一个简单的组件:

import {Component} from '@angular/core';

@Component({
  selector: 'service-bootstrap'
  template: ''
})
export class ServiceBootstrapComponent {}
这个组件什么都不做。现在,我们在顶级angular模块中声明这个组件

@NgModule({
  // ...providers, imports etc.
  declarations: [
    // ... existing declarations
    ServiceBootstrapComponent
  ],
  entryComponents: [
    // ... existing entry components
    ServiceBootstrapComponent
  ]
})
export class MyAngularModule {}
接下来,我们还需要将该组件的降级版本添加到angularjs模块中

最后,我们在index.html中加入这个组件

<body>
  <service-bootstrap></service-bootstrap>
  <!-- existing body contents -->
</body>


当angularjs在标记中找到该组件时,它需要初始化angular模块,以便能够呈现该组件。这样做的预期副作用是,提供程序等也会被初始化,并可用于可正常使用的
可注入

此线程中的答案帮助我找到了一个解决方案,但没有一个包含圣杯:

  • 在应用程序代码旁边创建一个
    服务boostrap
    组件不起作用,因为AngularJS不同于AngularJS,AngularJS是异步加载的。这会在引导Angular模块之前尝试获取Angular注入器时产生相同的错误
  • 创建一个封装AngularJS代码的
    服务引导组件
    是可行的,但随后我遇到了AngularJS组件内部的更改检测问题,如中所述
  • 在github问题中,有人建议编辑
    @angular/upgrade
    源代码,将
    false
    更改为
    true
    ,以强制在区域中创建组件。但在这种情况下,这似乎会导致性能问题(似乎会在用户事件中多次启动ngZone的代码)
  • 为了让应用程序正常工作,我需要:
  • 不要让ng组件包含AngularJS组件包含角度组件。我们只需要让AngularJS包含角度组件
  • 确保使用AngularJS服务的AngularJS组件是在第一个Angular组件之后创建的,该组件名为
    service bootstrap
  • 为了实现这一点,我创建了一个稍加修改的
    服务引导组件:

    import{Component,Output,EventEmitter,AfterViewInit}来自“@angular/core”;
    @组成部分({
    选择器:'服务引导',
    模板:``
    })
    导出类ServiceBootstrapComponent在ViewInit之后实现{
    @输出()
    public已初始化:EventEmitter=neweventemitter();
    公共ngAfterViewInit(){
    this.initialized.emit();
    }
    }
    
    在AngularJS模块中将此组件声明为
    entryComponent
    ,并调用
    DegradeComponent
    将其注册到AngularJS中:

    从'@angular/upgrade/static'导入{grademodule,gradeInjectable,gradeComponent};
    const bootstrapFn=(extraProviders:StaticProvider[])=>{
    const platformRef=platformBrowserDynamic(外部提供者);
    返回平台参考bootstrapModul
    
    const service = this.$injector.get('service');
    service.methos();