Angular2-OnInit:服务的订阅函数返回的值未分配给组件字段 [英] Angular2 - OnInit : Values returned from Service' subscribe function does not get assigned to Component field/s

查看:59
本文介绍了Angular2-OnInit:服务的订阅函数返回的值未分配给组件字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试Angular2,并且一直在关注他们的教程.

I'm trying out Angular2 and have been following their tutorials.

我目前有一个可以从json服务器获取数据的服务:

I currently have a Service that gets data from a json server:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';

import { Observable } from 'rxjs/Observable';

import { User } from './user';

@Injectable()
export class UserService {
  constructor(private http: Http) {}

  private usersUrl = 'http://localhost:3000/users';

  getUsers(): Observable<User[]> {
    return this.http.get(this.usersUrl) //the request won't go out until something subscribes to the observable
                    .map(this.extractData)
                    .catch(this.handleError); // pass an error message back to the component for presentation to the user but only if we can say something the user can understand and act upon
  }

  private extractData(response: Response) {
    if (response.status < 200 || response.status >= 300) {
       throw new Error('Bad response status: ' + response.status);
    }
    let body = response.json(); // parse JSON string into JavaScript objects

    return body.data || { };
  }

  private handleError (error: any) {
    // In a real world app, we might send the error to remote logging infrastructure before returning/sending the error
   let errMsg = error.message || 'Server error'; // transform the error into a user-friendly message

   return Observable.throw(errMsg); // returns the message in a new, failed observable
  }

}

还有我的组件:

import { Component, OnInit } from '@angular/core';

import { User } from '../common/user/user';
import { UserService } from '../common/user/user.service';

@Component({
  selector: 'app-nav',
  templateUrl: '/app/nav/nav.component.html',
  styleUrls: ['/app/nav/nav.component.css']
})
export class NavComponent implements OnInit {
  errorMsg: string;
  users: User[];

  constructor(private userService: UserService) { }

  getUsers() {
    this.userService
    .getUsers()
    .subscribe(
      function(users) {
        console.log('users ' + users);
        this.users = users;
        console.log('this.users ' + this.users);
      }, function(error) {
        console.log('error ' + error);
      });
    // users => this.users = users,
    // error => this.errorMsg = <any>error);
  }

  ngOnInit() {
    this.getUsers();
    console.log('ngOnit after getUsers() ' + this.users);
  }
}

我的问题是,getUsers()调用完成后,没有将从订阅函数返回的数据传递/分配给我的组件属性"users".我确实知道数据是从服务方法调用返回到组件的,因为我能够在userService().getUsers方法中记录数据.奇怪的是,虽然我先调用getUsers,但在getUsers方法中的console.logs之前,先在我的dev控制台上打印了ngOnInit上的console.log调用.

My problem is, the data returned from the subscribed function is not being passed/assigned to my Component property 'users' after the getUsers() invocation completes. I do know that the data is returned to the component from the service method call because I'm able to log the data within the userService().getUsers method. The weird thing is, the console.log invocation on my ngOnInit is being printed on my dev console first before the console.logs within my getUsers method, although I invoke the getUsers first:

  ngOnInit() {
    this.getUsers();
    console.log('ngOnit after getUsers() ' + this.users);
  }

Dev控制台屏幕截图:

Dev console screenshot:

推荐答案

这是因为this.getUsers()然后是this.userService.getUsers().subscribe(...)仅计划向服务器发出请求的调用.最终,当服务器的响应到达时(甚至在调用服务器之前已经执行过console.log('ngOnit after getUsers() ' + this.users);),然后执行传递给subscribe()的函数.

This is because this.getUsers() and then this.userService.getUsers().subscribe(...) only schedules a call to make a request to the server. Eventually when the response from the server arrives (console.log('ngOnit after getUsers() ' + this.users); was already executed before the call to the server was even made) then the function you passed to subscribe() is executed.

这应该做您想要的:

  getUsers() {
    return this.userService
    .getUsers()
    .map(
      (users) => {
        console.log('users ' + users);
        this.users = users;
        console.log('this.users ' + this.users);
      })
     .catch((error) => {
        console.log('error ' + error);
        throw error;
      });
    // users => this.users = users,
    // error => this.errorMsg = <any>error);
  }

  ngOnInit() {
    this.getUsers().subscribe(_ => {;
      console.log('ngOnit after getUsers() ' + this.users);
    });
  }

getUsers()中,我使用map()而不是subscribe,因此我们可以稍后进行订阅,以便能够在响应到达时执行代码.

In getUsers() I use map() instead of subscribe, so we can subscribe later in order to be able to get code executed when the response arrived.

然后在ngOnInit()中,我们使用subscribe()(必须使用subscribe(),否则将不会执行http.get()),并在响应到达时传递要执行的代码.

Then in ngOnInit() we use the subscribe() (subscribe() is necessary, otherwise would http.get() would never be executed) and pass the code we want to be executed when the response arrives.

我也将function ()更改为() =>.这种方式this在下面的代码块() => { ... }中起作用,否则就不会.

I also changed function () to () =>. This way this works inside the following code block () => { ... }, otherwise it wouldn't.

别忘了添加

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

否则这些运算符将不会重新识别.

otherwise these operators won't be recoginzed.

这篇关于Angular2-OnInit:服务的订阅函数返回的值未分配给组件字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆