angular 2+ Promises、Observable 和异步管道

angular 2+ Promises, Observable and async pipe

我正在 angular 4 和 运行 处理我的第一个项目,遇到一个小问题。

当我调用服务器时,有延迟,我学会了使用异步管道来显示我从服务器获取的数据。

但我 运行 遇到的问题是,例如,我向服务器发出了 HTTP 调用,现在我正在等待信息从服务器返回。但我需要这些信息来做一些数字 c运行ching。因此,我分配的正在等待来自服务器的信息的变量返回时未定义,因为 运行-time 的代码被执行并且没有可分配给它们的值。

ngOnInit(){
    this.settings = this.settingsService.getSettings();
    console.log("Logging Settings: " + this.settings);  // ends up being undefined
  }

onDoSomething(){
    return this.settings * gazillion;  // doesn't work 
}

进行服务调用并让 DoSomething 方法知道在您获得设置之前推迟的正确方法是什么?此外,如果您在整个应用程序中使用这些设置,您将如何存储它,这样您就不会在每次需要设置时不断地进行 HTTP 调用。

我的直觉是让 app.componenet.ts 进行调用和存储。

谢谢!

通常服务于 angular 2 return 个可观察对象。 这是因为 HTTP 请求使用来自服务器的数据 return 需要花费可变的时间。

我不确定 getsettings 到底在做什么,但一般设置如下:

//service layer
    function getSettings() {
        return this.http.get(`server-url`)
            .map((response: Response) => <any>response.json())
            .catch(this.handleError);
}

private handleError(error: Response) {
    return Observable.throw(error.json() || 'Server error');
}
//in your component
this.service.getSettings().subscribe(result => {this.settings = result}, error => {console.log("there was an error.")});

订阅部分在 http 请求响应客户端后被触发。

一路上有几件事可以帮助你:

  • 如果数据已准备好直接从服务器提供服务,则异步管道非常有用。如果您在组件中需要它,请不要使用异步管道,只需订阅即可。
  • Angular 将从 http 请求返回一个可观察对象,然后您可以使用 subcribe() 函数并提供您希望在检索数据或数据失败时发生的操作。

Here is a good tutorial on using http in an angular service

在您的特定情况下,您需要这样的东西:

ngOnInit(){
    this.settings = this.settingsService.getSettings().subscribe((settings)=>{
    this.settings = settings;
    console.log("Logging Settings: " + this.settings);
}

要回答您的第二个问题,Angular 服务,如果按照开发人员的预期完成,请遵循 Singleton Pattern 并且是整个应用程序的共享资源。这意味着访问它的所有内容都将接收与其他任何内容相同的实例。

这是 do 或 map 运算符的完美用例,具体取决于您实际想要实现的目标:

this.settings = this.settingsService.getSettings().do(settings => this.doSomething(settings));

如果你只是想要一个 "side effect",因为你实际上并不想影响你发送给显示器的数据,你只是想用它做一些与显示无关的事情,但是你需要它在序列中的某个点发生(我经常使用 do() 来隐藏页面范围的内容加载弹出窗口或其他东西)。 doSomething() return 是否是一个值并不重要,因为它不会被使用。

this.settings = this.settingsService.getSettings().map(settings => this.transformSettings(settings));

如果您想实际更改发送到显示器的数据,地图运算符在这种情况下会大量使用。 transformSettings() 必须 return 一个值,即您要具体显示的值,因为这将传递给最终订阅者。

对于第 2 部分,将结果存储在服务层的行为主题中,以便它始终可供需要它的任何组件使用:

private settingsSource = new BehaviorSubject(null);
settings$ = this.settingsSource.asObservable().filter(e => !!e); //this prevents the initial null value from being sent
loadSettings() {
    this.http.get('settings').map(r => r.json()).subscribe(this.settingsSource);
}
constructor(private http: HttpClient) {
  this.loadSettings();
}

然后让您的组件订阅 settings$,它会在到达那里时出现。