异步检索存储的令牌并在必要时在Angular应用中刷新

时间:2018-08-16 01:51:02

标签: angular typescript

我正在尝试实施一个利用Spotify的安全api的Spotify搜索应用。

我需要找出一种异步执行此操作的方法,而不必在每次调用时都重新进行身份验证。 Spotify的令牌有效期为一个小时,因此我几乎不需要刷新。

目标:

我希望它遵循以下逻辑流程:

1)检查存储的令牌 2)如果令牌丢失或过期,请检索新令牌并存储 3)将存储的令牌返回搜索功能

问题:

当前,应用将在检索新令牌之前执行调用。我确实设法一次将它包装在一个Promise中,但是搜索调用最初只执行一次,然后什么也没有执行。

我正在寻找有关如何处理异步if / else逻辑的建议。

我已经阅读了有关新的HttpInterceptor的信息,但它们似乎更适合于用户具有单独登录名的应用程序。此应用将使用客户端凭据。

我愿意接受任何对此有任何建议的建议!

以下是我的代码的一些相关示例:

spotify.service.ts

    import {Injectable, OnInit} from '@angular/core';
    import { HttpClient, HttpHeaders} from '@angular/common/http';
    import { map, mergeMap } from 'rxjs/operators';
    import { Observable, Timestamp} from '../../../node_modules/rxjs';
    import {Auth} from '../../../Auth';
    import { of } from 'rxjs';
    import { from } from 'rxjs';

    @Injectable()
    export class SpotifyService {
        private searchUrl: string;
        private artistUrl: string;
        private albumsUrl: string;
        private albumUrl: string;
        private authUrl: string;
        private authTime: number;

        constructor(private _http: HttpClient,
        private auth: Auth) {
            this.getAuth().subscribe();
        }

        searchMusic(str: string, type = 'artist') {
            return this.getAuth().pipe(mergeMap(res => {

                const headers = new HttpHeaders().set('Authorization', 'Bearer ' + this.auth.access_token);
                this.searchUrl = 'https://api.spotify.com/v1/search?query=' + str + '&offset=0&limit=20&type=' + type + '&market=US';
                return this._http.get(this.searchUrl,  {headers: headers }).pipe(map(resp => {
                    console.log(resp);
                        return resp;
                }));

            }));


        }



        getAccessToken() {
            this.authUrl = 'https://spot-auth.herokuapp.com/api/authorize';
            return this._http.get(this.authUrl);
        }


        getAuth() {
            const simpleObservable = new Observable((observer) => {
                // observable execution
                if (this.auth.access_token == null || this.authTime < (new                         
     Date().getSeconds() - 60)) {
                    observer.next(this.getAccessToken().pipe(map(res => {
                        this.authTime = new Date();
                        this.auth = res;
                    })));
                }
                observer.complete();
            });
            return simpleObservable;
        }


    }

search.component.ts

    import { Component } from '@angular/core';
    import {SpotifyService} from '../../services/spotify.service';
    import {Artist} from '../../../../Artist';

    @Component({
        moduleId: module.id,
        selector: 'search',
        templateUrl: 'search.component.html'
    })
    export class SearchComponent {
        searchStr: string;
        searchRes: Artist[];

        constructor(private _spotifyService: SpotifyService) {

        }

        searchMusic() {
            this._spotifyService.searchMusic(this.searchStr).subscribe(res => {
                this.searchRes = res.artists.items;
            });
        }
    }

search.component.html

    <h1>Need Music?</h1>
    <p class="lead">Use the ngSpotify app to browse new releases and find your favorite songs<br> All you get is this text and a mostly barebones HTML document.</p>

    <form>
        <div class="form-group">
            <input class="form-control" type="text" placeholder="Search Artists..." [(ngModel)]="searchStr" name="searchStr" (keyup)="searchMusic()">    
        </div>    
    </form>

    <div *ngIf="searchRes">
        <div *ngFor="let artist of searchRes">
            <div class="row">
                <div class="col-md-12">
                    <div class="search-res well">
                        <h4><a routerLink="/artist/{{artist.id}}">{{artist.name}}</a></h4>
                        <div>
                            <strong>Genres: </strong>
                            <span *ngFor="let genre of artist.genres">{{genre}}</span>    
                        </div>  
                    </div>    
                </div>
            </div> 
        </div>    
    </div>

0 个答案:

没有答案