【问题标题】:Ionic 3 How to ensure db data fetched before view is loadedIonic 3 如何确保在加载视图之前获取数据库数据
【发布时间】:2018-03-23 16:09:37
【问题描述】:

我正在使用基于令牌的身份验证,并且令牌已保存在数据库中。

当应用程序启动时,我需要从数据库中获取令牌并使其可用,然后再进行 API 调用。

最好的方法是什么:

在组件中:

ngOnit() {
storage.get('token').then((val) => {
    Make api call here 
});
}

或在共享服务中:

getToken() {
    return Promise((resolve, reject)=>{
       #if fetched once save in local var and resolve token  
       #or fetch from DB and resolve token  
    })
}

// On Component
this.sharedService.getToken().then((token)=>{
  //Make api call
}

有什么方法可以确保在加载视图之前获取数据库令牌并将其存储在共享服务中? storage.get 是一个“ES6 承诺”

关注是在加载视图升级到任何引导事件之前加载令牌的责任,因此不需要在每个组件中定义 onViewLoad。

【问题讨论】:

    标签: angular typescript ionic-framework ionic3


    【解决方案1】:

    我已经以这种方式实现了上述用例。

    我为CRUD 创建了ApiService,如下所示。code 是不言自明的,如果您需要更多信息,请告诉我。

    api-service.ts

    import { Injectable, } from '@angular/core';
    import { Http, Response } from '@angular/http';
    import { Observable } from 'rxjs/Observable';
    import { Headers, RequestOptions, BaseRequestOptions } from '@angular/http';
    import { Storage } from '@ionic/storage';
    import { Events } from 'ionic-angular';
    
    @Injectable()
    export class ApiService {
    
        constructor(private http: Http, private storage: Storage, private events: Events) { }
    
        createHeader(headers: Headers) {
            return new Promise((resolve, reject) => {
                this.storage.get('loggedInUser')
                    .then((token: any) => {
                        if (token) headers.append('Authorization', 'token ' + token.token);
                        resolve(headers);
                    }, err => {
                        resolve(headers);
                    });
            });
        }
    
        get(api) {
            let header = new Headers();
            return Observable.fromPromise(this.createHeader(header))
                .map(() => {
                    let options = new BaseRequestOptions();
                    options.withCredentials = true;
                    options.headers = header;
                    return options
                })
                .switchMap((options) => this.http.get(api, options))
                .catch((err: Error | Response) => {
                    if (err instanceof Response && err.status === 401) {
                        this.events.publish('token-expiration');
                    }
                    return Observable.throw(err);
                });
        }
    
        post(url, params): Observable<any> {
            return new Observable(observer => {
                let header = new Headers();
                this.createHeader(header)
                    .then(() => {
                        let options = new RequestOptions({ headers: header });
                        this.http.post(url, params, options)
                            .subscribe(response => {
                                observer.next(response);
                                observer.complete();
                            }, (e) => {
                                observer.error(e);
                            });
                    })
            })
        }
    
        delete(url) {
            return new Observable(observer => {
                let header = new Headers();
                this.createHeader(header)
                    .then(() => {
                        return this.http.delete(url, { headers: header, withCredentials: true })
                            .subscribe(response => {
                                observer.next(response);
                                observer.complete();
                            });
                    })
            });
        }
    
    }
    

    这里我在用户登录应用时创建了loggedInUser存储,也是一个provider,如下图。

    social-login.ts

    import { Injectable } from '@angular/core';
    import { ApiService } from "../providers";
    import { LocalCacheServiceProvider } from "../local-cache-service/local-cache-service";
    import { UserService } from "../user-provider";
    import { Storage } from '@ionic/storage';
    
    
    @Injectable()
    export class SocialLoginProvider {
    
      constructor(private apiService: ApiService, private localCacheService: LocalCacheServiceProvider, private userService: UserService, private storage: Storage) {
      }
    
      //login To App
      loginToApp(url: string, data: string) {
        this.apiService.post(url, { access_token: data })
          .map((res: any) => res.json())
          .subscribe(res => {
            this.setUserLocally(res);
          });
      }
    
      //set User Locally
      setUserLocally(user) {
        this.localCacheService.clearAllKeys().then(() => {
          this.userService.setLoggedInUser(user);
          this.storage.set('loggedInUser', user);
        });
      }
    }
    

    之后,我可以通过我的任何provider(用于CRUD 操作)使用上述服务(即ApiService),如下所示。

    这是ArticleService

    article-service.ts

    import { Injectable } from '@angular/core';
    import { Observable } from "rxjs/Observable";
    import 'rxjs/add/operator/map';
    import { config } from '../config/config';
    import { ApiService } from './api-service';
    
    
    @Injectable()
    export class ArticleService {
    
        constructor(private apiService: ApiService) {
        }
    
       getBookById(id) {
            return this.apiService.get(`${config.getBookById}${id}/`).map((res: any) => res.json());
        }  
    }
    

    以上方法对我来说非常有效。希望这种方法也能对您有所帮助。如果您需要更多帮助,请告诉我。

    【讨论】:

    • 我喜欢从 api 服务而不是每个组件获取和添加令牌的概念。但是每次直接从 db 中获取令牌不是开销,我可以使用它在获取后存储在局部变量中吗?
    • 当我们考虑到应用程序的安全性时,我认为这是最好的。我在这里看不到任何性能问题。而且您也可以很好地处理令牌过期用例。见.catch((err: Error | Response) =&gt; { if (err instanceof Response &amp;&amp; err.status === 401) { this.events.publish('token-expiration'); } return Observable.throw(err); });
    • 是的,实际上我已经将token 存储在localstorage 中,即loggedInUser
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多