Angular 2服务的异步初始化

Veg*_*sen 19 typescript angular2-services angular

我有一个Angular 2服务,它需要在初始化时进行异步工作,并且在初始化完成之前不应该可用.

@Injectable()
export class Api {
    private user;
    private storage;

    constructor(private http: Http) {
        this.storage = LocalStorage;
        this.storage.get('user').then(json => {
            if (json !== "") {
                this.user = JSON.parse(json);
            }
        });        
    }

    // one of many methods
    public getSomethingFromServer() {
        // make a http request that depends on this.user
    }
}
Run Code Online (Sandbox Code Playgroud)

按照目前的情况,此服务已初始化,并立即返回到使用它的任何组件.然后该组件调用getSomethingFromServer()ngOnInit,但此时Api.user未初始化,因此发送了错误的请求.

生命周期钩子(OnInit,OnActivate等)不能用于服务,只能用于组件和指令,所以我不能使用它们.

get()调用中存储Promise 将需要依赖于用户的所有不同方法等待它,从而导致大量代码重复.

在Angular 2中进行异步初始化服务的推荐方法是什么?

Veg*_*sen 6

在与Thierry的答案进行了一些讨论之后,我发现它只能工作一次,但它确实让我走上了正确的道路.我不得不存储用户的承诺,并创建一个新的observable,然后使用flatMap-ed.

@Injectable()
export class Api {
  private userPromise: Promise<User>;

  constructor(private http: Http) {
    this.userPromise = LocalStorage.get('user').then(json => {
      if (json !== "") {
        return JSON.parse(json);
      }
      return null;
    });        
  }

  public getSomethingFromServer() {
      return Observable.fromPromise(this.userPromise).flatMap((user) => {
        return this.http.get(...).map(...);
      });
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这确保了flatMap函数在每次调用时都会获得用户,而不仅仅是第一次,就像在Thierry的回答中那样.


Thi*_*ier 5

您可以利用observable与flatMap运算符一起执行此操作.如果用户不在那里,您可以等待它,然后链接目标请求.

这是一个示例:

@Injectable()
export class Api {
  private user;
  private storage;
  private userInitialized = new Subject();

  constructor(private http: Http) {
    this.storage = LocalStorage;
    this.storage.get('user').then(json => {
      if (json !== "") {
        this.user = JSON.parse(json);
        this.userInitialized.next(this.user);
      }
    });        
  }

  // one of many methods
  public getSomethingFromServer(): Observable<...> {
    // make a http request that depends on this.user
    if (this.user) {
      return this.http.get(...).map(...);
    } else {
      return this.userInitialized.flatMap((user) => {
        return this.http.get(...).map(...);
      });
    }
  }
}
Run Code Online (Sandbox Code Playgroud)