【问题标题】:Angular2 service not being injected as singletonAngular2服务未作为单例注入
【发布时间】:2017-06-24 09:29:01
【问题描述】:

我定义了以下服务:

@Injectable()
export class UserService {

private _users: User[] = []
private _currentUser:User;

///Creates an instance of the Angular2 Http Service 
 constructor(private _http: Http) {console.log("in the constructor"; }

这是从登录组件调用的:

@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
 })
export class LoginComponent implements OnInit {
returnUrl: string;

constructor(private _userService: UserService,
          private route: ActivatedRoute,
          private router: Router)   { }

 validateUser(username: string, password: string): boolean {
  var loggedOnUser = this._userService.checkLogin(username, password);
  ...//check if logged on
 this.router.navigate([this.returnUrl]);

  return true;
 }

但是,当登录成功时,它会重定向到本地路由,并且身份验证守卫会启动用户服务的新实例,因为它是一个新实例,所以会为经过身份验证的用户返回 undefined

@Injectable()
export class AuthGuard implements CanActivate {

constructor(private router: Router, private _userService: UserService) { }

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

    if (this._userService.getAuthenticatedUser()) //is undefined?????
    {
        return true;
    }

    // not logged in so redirect to login page with the return url
    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url    }});
    return false;
}
}

我的模块是这样声明的:

@NgModule({
 declarations: [
AppComponent,
LoginComponent,
HomeComponent,
ManageUsersComponent,
StandingDataComponent
 ],
 imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
 ],
providers: [AuthGuard,UserService],
bootstrap: [AppComponent]
})
export class AppModule { }

我的路由类如下:

const appRoutes: Routes = [
{path: '', component: HomeComponent, canActivate:[AuthGuard]},    
{ path: 'login', component: LoginComponent },
{path: 'home', 
component:HomeComponent, canActivate:[AuthGuard],
children: [{path: 'manageusers', component: ManageUsersComponent, outlet: 'innerPage'},
            {path: 'standingdata', component: StandingDataComponent, outlet: 'innerPage'}]
}, 
// otherwise redirect to home
{ path: '**', redirectTo: '' }];

@NgModule({
    imports: [RouterModule.forRoot(appRoutes)],

exports: [RouterModule]
})
export class AppRoutingModule { }

用户服务构造函数代码在登录页面被点击和身份验证成功时触发。

我的理解是,当在组件和模块中都定义了 UserService 时会发生这种问题,但在我的情况下,模块是唯一定义它的地方。

【问题讨论】:

  • 问题是 XY 问题,假设它不是单例会导致错误的答案。从上面的代码来看,它只能是单例。如果您对此有疑问,请通过将_userService 暴露给全局变量并检查它们是否相等来检查这一点,您是唯一可以做到这一点的人。问题需要MCVE
  • 我认为构造函数中的代码多次触发的事实表明它不是单例??
  • 如果您只有一个地方有"in the constructor",那么可以。您在constructor(private _http: Http) {console.log("in the constructor"; } 中存在语法错误这一事实表明实际代码与您发布的代码在某些方面有所不同。需要 MCVE 才能使该问题不被视为离题。一把小提琴可能会有所帮助。根据我对 A2 DI 的了解,如果您在其他地方没有 providers: [UserService],就不可能有不同的实例。

标签: angular singleton


【解决方案1】:

不确定现在的样子,但在 Angular2 rc.4 中我可以使用这种方法:

bootstrap.ts

import {AppComponent} from './components/AppComponent;
import { singletonServiceNr1, singletonServiceNr2) from './services/Services;

let singletonServices = [
  singletonServiceNr1,
  singletonServiceNr2
];

bootstrap(AppComponent, [singletonServices]);

比您以正常方式在所需组件中注入singletonServiceNr1singletonServiceNr2。他们现在是单身人士。


在你的情况下,你应该做同样的事情:

@NgModule({
 declarations: [
AppComponent,
LoginComponent,
HomeComponent,
ManageUsersComponent,
StandingDataComponent
 ],
 imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
 ],
providers: [AuthGuard,UserService],
bootstrap: [AppComponent, UserService]     // note the change here
})
export class AppModule { }

【讨论】:

  • 当我执行“未处理的 Promise 拒绝:组件 UserService 不是任何 NgModule 的一部分或该模块尚未导入您的模块”时出现错误
  • Echh,正如我所说 - 我还没有进入模块,所以我无法回答你的问题。我仍然卡在 rc4 上。
【解决方案2】:

在以下stackoverflow中找到了解决方案:

Angular2 router.navigate refresh page

这导致我在 Internet Explorer 中对其进行了测试,结果正常(它在 Chrome 中不起作用)

原来执行下面一行的时候整个页面都在刷新:

this.router.navigate([this.returnUrl]);

这导致用户服务再次重新加载,因为按钮上没有 type,Chrome 的默认操作是将按钮单击视为提交。

解决方法是将标签 type="button" 添加到 html 中的登录按钮

<button type="button" class="btn btn-primary"(click)="validateUser(username, password)">Login</button>

它现在适用于所有浏览器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 2016-05-09
    • 2017-06-27
    相关资源
    最近更新 更多