Ionic存储“get”仅在方法内的第二次调用时返回null

时间:2017-08-12 23:58:00

标签: angular ionic-framework storage observable angular-promise

我正面临着Ionic Storage的一个非常奇怪的问题。我有一个方法从存储中读取一个值,并返回一个包含对应于该对象的promise:

private getAuthorizedOptions(): Promise<RequestOptions>
  {
        return this._storage.get('bdAccessToken')
            .then(v => {
                console.log("access token: ", v);
                let token = v;
                let header = new Headers({
                    'Authorization': 'Bearer ' + token
                });
                let ro = new RequestOptions({
                    headers: header
                });
                let options = new RequestOptions();
                if (options.headers) options.headers.delete("Authorization");
                options.headers = header;
                return options;
            });
  }

现在我有另一个方法,它会在一系列动作中调用上面的方法两次:

get(url:string, options?:RequestOptions): Observable<Response>
    {   
        return Observable.fromPromise(this.getAuthorizedOptions())
                .mergeMap((options) => 
                {
                    return super.get(url, options)
                        .catch(err => {
                            if (err && err.status === 401) 
                            {
                                return this._authService.refreshToken()
                                    .mergeMap(r => 
                                        {
                                            return Observable.fromPromise(this.getAuthorizedOptions())
                                                .mergeMap(opt => {
                                                    return super.get(url, opt)
                                            });

                                        }
                                    )
                                    .catch(err2 => {
                                        console.log("redirecting.");
                                        this.redirect();
                                        return Observable.throw(err2);
                                    });
                            }
                            else {
                                return Observable.throw(err);
                            }
                        });
                });
    }

现在追踪这些方法显示出一些奇怪的东西。第一次调用“getAuthorizedOptions()”方法时,它可以很好地从存储中读取“bdAccessToken”值。第二次调用时,返回的值为NULL。

我已经把头发拉了两天,任何帮助都会得到赞赏,就像你以前从未被赏识过一样!大声笑!

1 个答案:

答案 0 :(得分:2)

我遇到了一些存储问题和古怪的行为,最终与异步问题有关。

没有以期望/预期的顺序执行的事情。

所以我最终使我的服务处于有状态并监视了一个BehaviourSubject事件。

import { Injectable }       from '@angular/core';
import { Storage }          from '@ionic/storage';
import { Server }           from './../model/server';
import { Subscription }     from 'rxjs/Subscription';
import { BehaviorSubject }  from "rxjs/BehaviorSubject";

export class LoginService {
  private static readonly SERVER = 'server';
  private servers$:BehaviorSubject<Server[]>;
  private servers: Server[];
  public serversSubs:Subscription

  constructor(public storage: Storage) {

    this.servers$ = new BehaviorSubject([] as Server[]);
    this.nextServersFromGetLocal(); // May need to be after subscribe.. Hot off presses.. 
    this.serversSubs = this.servers$.subscribe((servers:Server[]) =>
        this.servers = servers);
  }


  private nextServersFromGetLocal():void {
    this.storage.get(LoginService.SERVER).
      then( (value:string) =>  {
            this.servers$.next( JSON.parse(value) as Server[] );
                               }
      ).catch( ()           => {
             this.servers$.next( [] as Server[] );
                               }
      );
  }     

  private nextServersFromSetLocal(servers:Server[]): void {
    let data = JSON.stringify(servers);
    this.storage.set(LoginService.SERVER, data);
    this.servers$.next(servers);
  }

  getServers$(): BehaviorSubject<Server[]> {
    return this.servers$;
  }

  addServer(addServer:Server): void {
     // other code too...
     this.servers.push(addServer);
     this.nextServersFromSetLocal(this.servers);
  }

  changeServer(changeServer:Server): void {
    // other code too...
    this.nextServersFromSetLocal(this.servers);
  }

  deleteServer(deleteServer:Server): void {
    // other code too..
    this.nextServersFromSetLocal(this.servers);
  }
}

这种重构具有额外的好处,即简化了对服务执行CRUD操作的其他代码,因为异步行为不必内联复杂的嵌套/重复promise / then / catch代码块。希望这会对你有所帮助。

您可以在Ionic app here的上下文中了解这是如何工作的,因为我发布了相关问题,您可以在屏幕截图中看到此视图的HTML视图