angular - مشکل کار نکردن redirectTo در Angular2+ هنگام هدایت به یک لینک با canActivate


عملیات redirectTo نتوانست به لینکی با canActivate هنگام ورود من هدایت شود.

عملکرد redirectTo وقتی که خارج شدم خوب است، آن به کامپوننت /login من هدایت میکند و بعد از ورود، redirectTo به /index هدایت میشود.

اما وقتی وارد شدهام، روی '' گیر میکند.

من باید console.log را به authGuard خود اضافه میکردم، و آدرس بازگشتی "/index" واقعاً به آن تابع رفت در موقعیت چسبیدن به '' بدون اینکه در ابزار توسعه کرش کند.

اما بعد از کامنت گذاشتن روی canActivate، redirectTo مانند قبل درست کار میکند.

راستی، authGuard من با canActivate در شرایط دیگر خوب کار میکند (به جز redirecTo)

این فایل app-routing.module.ts من است

/* import... */

const appRoutes: Routes = [
    { path: 'login', component: LoginComponent },
    { path: '', redirectTo : '/index', pathMatch: 'full' },
    { path: '**', component: PageNotFoundComponent }
];

/* ngmodel and export ... */

و این هم فایل index-routing.module.ts من

/* import ... */

const indexRoutes: Routes = [
    {
        path: 'index',
        component: IndexComponent,
        canActivate: [AuthGuard], //<- if comment this will work
    },
];

/*   ngmodel and export ... */

در اینجا فایل auth-guard.module.ts من است

/* import ... */

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
        private authService: AuthService,
        private router: Router
    ) { }
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        let url: string = state.url;
        //redirectTo did get in here
        console.log(url); //<-- this show /index 

        return this.checkLogin(url);
    }

    checkLogin(url: string): boolean {
        if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
            return true;
        }
        this.authService.get_login_data()
         .subscribe(
            data => {
                this.authService.login_data = data;
                if (data.userprofile || !data.need_login) {
                    return true;
                }
                this.authService.redirectUrl = url;
                this.router.navigate(['/login']);
                return false;
            },
            error => { this.authService.errMsg = <any>error;}
        );
    }
}

راستی من پروژهام را به انگولار ۴.۰.۱ بهروزرسانی کردهام

متشکرم.

بهروزرسانی:

من بازگشت گارد خود را از بولی به Observable تغییر دادهام

اما هنوز هم کار نمیکند.

در اینجا کدی است که من استفاده کرده بودم.

    checkLogin(url: string): Observable<boolean> {
        if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
            console.log('gonna return observable true');
            return Observable.of(true);
            //return true;
        }
        this.authService.get_login_data()
        .subscribe(
            data => {
                this.authService.login_data = data;
                if (data.userprofile || !data.need_login) {
                    console.log('in subscribe and gonna return observable true');
                    return Observable.of(true);
                    //return true;
                }
                this.authService.redirectUrl = url;
                this.router.navigate(['/login']);
                return Observable.of(false);
                //return false;
            },
            error => { this.authService.errMsg = <any>error;}
        );
    }

در کنسول من، پیغام در اشتراکگذاری و قرار است Observable صحیح را برگرداند آمد

بهروزرسانی:

بعد از بررسی این

AuthGuard قبل از بررسی کاربر منتظر تمام شدن احراز هویت نمیماند

مشکل ممکن است این باشد که canActivate تا پایان subscribe صبر نمیکند.

پاسخ شماره ۱

در شما checkLogin() از AuthGuard:

checkLogin(url: string): boolean {
    if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
        return true;
    }
    this.authService.get_login_data()
     .subscribe(
        data => {
            this.authService.login_data = data;
            if (data.userprofile || !data.need_login) {
                return true;
            }
            this.authService.redirectUrl = url;
            this.router.navigate(['/login']);
            return false;
        },
        error => { this.authService.errMsg = <any>error;}
    );
}

نوع بازگشتی آن بولین است، در برخی شرایط مقدار true را باز میگرداند، اشکالی ندارد. اما، قسمت بعدی مشکل دارد. شما چیزی بازنگرداندهاید تا زمانی که نتیجه را مشترک شوید و بر اساس آن نتیجه بازگردانید.

این بدان معناست که این تابع مقدار undefined برمیگرداند، بنابراین بررسی canActivate کار نخواهد کرد.

[بهروزرسانی شده] شما میخواهید دادههای کاربر را از نتیجه تنظیم کنید، باید از do() در authService.get_login_data() خود برای تنظیم آن استفاده کنید. وقتی نتیجه را مشترک میشوید، این تابع 'do' فراخوانی میشود. و در checkLogin() خود از .map() به جای subscribe() استفاده کنید تا دادههای نتیجه ورود به سیستم را به بولین تبدیل کنید.

در این وضعیت، شما باید یک نوع Observable بازگردانید، مانند:

checkLogin(url: string): Observable<boolean> {
if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
    return Observable.of(true); // wrap true in Observable
}
return this.authService.get_login_data()
 .map(
    data => {
        if (data.userprofile || !data.need_login) {
            return true;
        }
        this.authService.redirectUrl = url;
        this.router.navigate(['/login']);
        return false;
    },
    error => { this.authService.errMsg = <any>error;}
);

}

پاسخ شماره ۲

من مشکل خود را با تغییر subscribe به map حل کردهام.

صدا زدن تابع ناهمزمان توسط canActivate() در Angular2

این کد من بعد از ویرایش است.

checkLogin(url: string): Observable<boolean>|boolean {
    if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
        console.log('gonna return observable true');
        return Observable.of(true);
    }   
    return this.authService.get_login_data()
    .map(
        data => {
            this.authService.login_data = data;
            if (data.userprofile || !data.need_login) {
                console.log('in subscribe and gonna return observable true');
                //return Observable.of(true);
                return true;                                                                                                                                                
            }   
            this.authService.redirectUrl = url;
            this.router.navigate(['/login']);
            //return Observable.of(false);
            return false;
        },  
        error => { this.authService.errMsg = <any>error;}
    );  
}  

در مپ وقتی که Observable(true) برمیگردانم، خطا میگیرم

Type 'Observable<Observable<boolean>>' is not assignable to type 'boolean | Observable<boolean>'.

ممنون از کمک و پیشنهادها.