说明
当promise被拒绝时,Auth Guard总是会产生错误。(
)ERROR Error: Uncaught (in promise): [object Boolean]
at resolvePromise (zone.js:814)
at resolvePromise (zone.js:771)
at zone.js:873
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:4053)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:595)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:500)
at invokeTask (zone.js:1540)
重现步骤:
// user.guard.ts
import { AuthService } from './../../services/auth/auth.service';
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable()
export class UserGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router){}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
return new Promise ((resolve, reject) => {
this.authService.isAuthenticated().then(
(res) => {
resolve(true);
},
(rej) => {
this.router.navigate(['landing']);
reject(false);
}
);
});
}
}
// auth.service.ts
import { AuthTokenService } from './../auth-token/auth-token.service';
import { Injectable } from '@angular/core';
import { Storage } from "@ionic/storage";
import { JwtHelperService } from "@auth0/angular-jwt";
@Injectable({
providedIn: 'root'
})
export class AuthService {
private jwtHelper: JwtHelperService;
constructor(
private storage: Storage,
private authTokenService: AuthTokenService
) {
this.jwtHelper = new JwtHelperService();
}
/**
* Check if a user is authenticated with a valid jwt token
*
* It fetches the currently stored token from localStorage
* and checks if it's a valid, non-expired token.
*
* @returns { Promise<boolean> } true = valid authenticated token; false = invalid/missing/expired token
* @memberof AuthProvider
*/
public isAuthenticated(): Promise<any> {
// create a new Promise for easier handling the auth state
return new Promise<boolean>((resolve, reject) => {
return this.getTokenFromStorage()
.then((res) => {
// res should be a AuthToken object
let token = <any>res;
if (!this.jwtHelper.isTokenExpired(token)) {
// user is logged in and has an non-expired token
resolve(true);
}
// user is logged in but has an expired token
reject(false);
})
.catch((err) => {
reject(false);
});
});
}
// app-routing.module.ts
import { UserGuard } from './guards/user/user.guard';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: '',
redirectTo: 'landing',
pathMatch: 'full'
},
{
path: 'landing',
loadChildren: './pages/landing/landing.module#LandingPageModule'
},
{
path: 'home',
loadChildren: './pages/home/home.module#HomePageModule',
canActivate: [UserGuard]
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
输出:
我的ionic info
:
(在您的项目中,如果适用)
下面。 `ionic info&lt; / code&gt;是一个打印出环境信息的CLI命令。
- &GT;
$ ionic info
cli packages: (C:\Users\Christian\AppData\Roaming\npm\node_modules)
@ionic/cli-utils : 2.0.0-rc.6
ionic (Ionic CLI) : 4.0.0-rc.6
global packages:
cordova (Cordova CLI) : not installed
local packages:
@angular-devkit/core : 0.6.0
@angular-devkit/schematics : 0.6.0
@angular/cli : 6.0.1
@ionic/schematics-angular : 1.0.0-rc.6
Cordova Platforms : none
Ionic Framework : @ionic/angular 4.0.0-alpha.7
System:
Android SDK Tools : 26.1.1
NodeJS : v8.11.1
npm : 6.1.0
OS : Windows 10
Environment Variables:
ANDROID_HOME : C:\android-sdk
其他信息:
defaultErrorLogger | @ | core.js:1598
-- | -- | --
| push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError | @ | core.js:1647
| next | @ | core.js:4727
| schedulerFn | @ | core.js:3712
| push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub | @ | Subscriber.js:253
| push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next | @ | Subscriber.js:191
| push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next | @ | Subscriber.js:129
| push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next | @ | Subscriber.js:93
| push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next | @ | Subject.js:53
| push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit | @ | core.js:3704
| (anonymous) | @ | core.js:4084
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke | @ | zone.js:388
| push../node_modules/zone.js/dist/zone.js.Zone.run | @ | zone.js:138
| push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular | @ | core.js:4021
| onHandleError | @ | core.js:4084
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError | @ | zone.js:392
| push../node_modules/zone.js/dist/zone.js.Zone.runGuarded | @ | zone.js:154
| _loop_1 | @ | zone.js:677
| api.microtaskDrainDone | @ | zone.js:686
| drainMicroTaskQueue | @ | zone.js:602
| push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask | @ | zone.js:500
| invokeTask | @ | zone.js:1540
| globalZoneAwareCallback | @ | zone.js:1566
| IndexedDB (async) | |
| (anonymous) | @ | localforage.js:826
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke | @ | zone.js:388
| onInvoke | @ | core.js:4062
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke | @ | zone.js:387
| push../node_modules/zone.js/dist/zone.js.Zone.run | @ | zone.js:138
| (anonymous) | @ | zone.js:872
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask | @ | zone.js:421
| onInvokeTask | @ | core.js:4053
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask | @ | zone.js:420
| push../node_modules/zone.js/dist/zone.js.Zone.runTask | @ | zone.js:188
| drainMicroTaskQueue | @ | zone.js:595
| push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask | @ | zone.js:500
| invokeTask | @ | zone.js:1540
| globalZoneAwareCallback | @ | zone.js:1566
| IndexedDB (async) | |
| (anonymous) | @ | localforage.js:595
| ZoneAwarePromise | @ | zone.js:891
| _getConnection | @ | localforage.js:578
| _getOriginalConnection | @ | localforage.js:628
| (anonymous) | @ | localforage.js:790
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke | @ | zone.js:388
| onInvoke | @ | core.js:4062
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke | @ | zone.js:387
| push../node_modules/zone.js/dist/zone.js.Zone.run | @ | zone.js:138
| (anonymous) | @ | zone.js:872
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask | @ | zone.js:421
| onInvokeTask | @ | core.js:4053
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask | @ | zone.js:420
| push../node_modules/zone.js/dist/zone.js.Zone.runTask | @ | zone.js:188
| drainMicroTaskQueue | @ | zone.js:595
| Promise.then (async) | |
| scheduleMicroTask | @ | zone.js:578
| push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask | @ | zone.js:410
| push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask | @ | zone.js:232
| push../node_modules/zone.js/dist/zone.js.Zone.scheduleMicroTask | @ | zone.js:252
| scheduleResolveOrReject | @ | zone.js:862
| ZoneAwarePromise.then | @ | zone.js:962
| setDriver | @ | localforage.js:2234
| LocalForage | @ | localforage.js:2040
| 4.3 | @ | localforage.js:2296
| s | @ | localforage.js:7
| e | @ | localforage.js:7
| (anonymous) | @ | localforage.js:7
| push../node_modules/localforage/dist/localforage.js | @ | localforage.js:7
| ./node_modules/localforage/dist/localforage.js | @ | localforage.js:7
| __webpack_require__ | @ | bootstrap:81
| ./node_modules/@ionic/storage/dist/storage.js | @ | index.js:24
| __webpack_require__ | @ | bootstrap:81
| ./node_modules/@ionic/storage/dist/index.js | @ | index.js:2
| __webpack_require__ | @ | bootstrap:81
| ./src/app/services/auth-token/auth-token.service.ts | @ | api.service.ts:9
| __webpack_require__ | @ | bootstrap:81
| ./src/app/services/auth/auth.service.ts | @ | auth-token.service.ts:8
| __webpack_require__ | @ | bootstrap:81
| ./src/app/guards/user/user.guard.ts | @ | app.module.ts:64
| __webpack_require__ | @ | bootstrap:81
| ./src/app/app.module.ts | @ | app.component.ts:12
| __webpack_require__ | @ | bootstrap:81
| ./src/main.ts | @ | environment.ts:16
| __webpack_require__ | @ | bootstrap:81
| 0 | @ | main.ts:12
| __webpack_require__ | @ | bootstrap:81
| checkDeferredModules | @ | bootstrap:43
| webpackJsonpCallback | @ | bootstrap:30
| (anonymous) | @ | main.js:1