【问题标题】:Ionic 4 - How to implement canActivate on one route using guardsIonic 4 - 如何使用警卫在一条路线上实现 canActivate
【发布时间】:2020-03-29 01:52:33
【问题描述】:

我的离子应用程序中有两条路线,欢迎页面和主页,欢迎用户必须回答一个问题,之后,他会重定向到主页,我想要做的是跳过第一条路线如果用户已经回答了问题。

这是我的警卫:

export class CheckWelcomeGuard implements CanActivate {
constructor(private router: Router, private dbstorage: DatabaseService) {}

canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
): boolean {
    this.dbstorage.getDatabaseState().subscribe(ready => {
    if (ready) {
        this.dbstorage.checkSettingsValue("WELCOME_PAGE_PASSED").then(data => {
        if (data) {
            return true;
        }
        });
    }
    });
    this.router.navigate(["/welcome"], {
    queryParams: { redirect: state.url },
    replaceUrl: true
    });
    return false;
}
}

取决于此,重定向发生在检查甚至执行之前!不断保持重定向到欢迎页面!

private database: SQLiteObject;
private dbReady: BehaviorSubject<boolean> = new BehaviorSubject(false);

settings = new BehaviorSubject([]);

constructor(
private platform: Platform,
private sqlite: SQLite,
private http: HttpClient
) {
this.platform.ready().then(() => {
    this.createDatabaseObject();
});
}

createDatabaseObject() {
this.sqlite
    .create({
    name: "testapp.db",
    location: "default"
    })
    .then((db: SQLiteObject) => {
    this.database = db;
    this.seedDatabase();
    });
}

seedDatabase() {
this.http
    .get("assets/testapp.sql", { responseType: "text" })
    .subscribe(sql => {
    this.database.executeSql(sql, [])
        .then(() => {
        // this.clearSettings();
        console.log('Executed SQL');
        this.dbReady.next(true);
        })
        .catch(e => console.log(e));
    });
}

// Database state
// ready: true
// not ready: false
getDatabaseState() {
    return this.dbReady.asObservable();
}

【问题讨论】:

    标签: angular ionic-framework


    【解决方案1】:

    问题是您对this.dbstorage.getDatabaseState().subscribe... 的调用是异步操作,因此它是非阻塞的。这意味着浏览器将进行调用但不会等待答案,而是继续正常执行您的代码,在这种情况下为this.router.navigate(["/welcome"], ...。因此,无论this.dbstorage.getDatabaseState().subscribe... 的结果如何,都将始终调用this.router.navigate(["/welcome"],...。您需要让代码等待数据库响应。我喜欢用这样的 Promises 来做:

    export class CheckWelcomeGuard implements CanActivate {
        constructor(private router: Router, private dbstorage: DatabaseService) { }
    
        async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
            const ready = await this.dbstorage.getDatabaseState().toPromise();
    
            if (ready) {
                const data = await this.dbstorage.checkSettingsValue("WELCOME_PAGE_PASSED");
    
                if (data) {
                    return true;
                } else {
                    this.router.navigate(["/welcome"], {
                        queryParams: { redirect: state.url },
                        replaceUrl: true
                    });
                    return false;
                }
            } else {
                this.router.navigate(["/welcome"], {
                    queryParams: { redirect: state.url },
                    replaceUrl: true
                });
                return false;
            }
    
        }
    }

    canActivate 也接受 Observables 作为返回值并且也能正常工作。这是另一种方式。

    【讨论】:

      【解决方案2】:

      我不确定这是要走的路,但这是一种方法。

      我假设 getDatabaseState()checkSettingsValue() 返回一个 Observable。
      Angular 会自动订阅 canActivate 方法返回的 Observable。

      export class CheckWelcomeGuard implements CanActivate {
      
        constructor(
          private router: Router,
          private dbstorage: DatabaseService
        ) {}
      
        canActivate(
          route: ActivatedRouteSnapshot,
          state: RouterStateSnapshot
        ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
      
          return this.dbstorage.getDatabaseState()
            .pipe(
              switchMap(ready => !ready
                ? this.redirectToWelcome(state)
                : this.dbstorage.checkSettingsValue('WELCOME_PAGE_PASSED')
                  .pipe(
                    switchMap(data => !data
                      ? this.redirectToWelcome(state)
                      : of(true)
                    )
                  )
              )
            );
        }
      
        redirectToWelcome(state: RouterStateSnapshot): Promise<boolean> {
          return this.router.navigate(['/welcome'], {
            queryParams: { redirect: state.url },
            replaceUrl: true
          });
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2019-07-02
        • 1970-01-01
        • 2018-01-02
        • 1970-01-01
        • 1970-01-01
        • 2020-02-18
        • 2017-05-21
        • 1970-01-01
        • 2019-06-03
        相关资源
        最近更新 更多