[英]Angular OnInit : Values returned from Service subscribe returns Empty blank because API has not Called yet
[英]Angular2 - OnInit : Values returned from Service' subscribe function does not get assigned to Component field/s
我正在嘗試 Angular2 並一直在關注他們的教程。
我目前有一個從 json 服務器獲取數據的服務:
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() 調用完成后,從訂閱函數返回的數據沒有傳遞/分配給我的組件屬性“用戶”。 我確實知道數據從服務方法調用返回到組件,因為我能夠在 userService().getUsers 方法中記錄數據。 奇怪的是,我的 ngOnInit 上的 console.log 調用首先在我的 getUsers 方法中的 console.logs 之前打印在我的開發控制台上,盡管我首先調用了 getUsers:
ngOnInit() {
this.getUsers();
console.log('ngOnit after getUsers() ' + this.users);
}
開發控制台截圖:
這是因為this.userService.getUsers().subscribe(...)
this.getUsers()
和this.userService.getUsers().subscribe(...)
只安排調用向服務器發出請求。 最終當來自服務器的響應到達時( console.log('ngOnit after getUsers() ' + this.users);
在調用服務器之前已經執行了)然后你傳遞給subscribe()
的函數被執行.
這應該做你想做的:
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,因此我們可以稍后訂閱,以便能夠在響應到達時執行代碼。
然后在ngOnInit()
我們使用subscribe()
( subscribe()
是必要的,否則http.get()
將永遠不會被執行)並在響應到達時傳遞我們想要執行的代碼。
我還將function ()
更改為() =>
。 這樣this
可以在下面的代碼塊() => { ... }
,否則就不會。
不要忘記添加
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
否則這些運算符將不會被識別。
對我來說,這就像魔術一樣,我需要從 api 獲取數據來初始化數據表組件
1- 在您的 http 服務上創建正常的 get 請求,如下所示:
public get(url: string):Observable<any> {
return this.http.get<any>( url );
}
2- 在您的組件上:
constructor(private HttpSvc: HttpService) {}
ngOnInit() {
this.render();
}
render() {
let options = this.options || {};
this.HttpSvc.Get('your api url').subscribe(data => {
this.Tableset = data;
options = {
data: this.Tableset.data,
columns: this.Tableset.columns,
dom: 'Bfrtip',
buttons: this.Tableset.buttons,
autoWidth: false,
pageLength: 2,
retrieve: true,
responsive: true
};
}, err => {console.log(err); },
() => {
this.renderDetails(options); //<-- can call any other method after call end
});
}
這里是完整的示例鏈接
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.