在打字稿文件中使用 .subscribe 之外的数据
use data outside of .subscribe in typescript file
我是 typescript/ionic 4 的新手。我正在尝试访问存储在 firebase 中的数据并在我的打字稿文件中使用它。在 .subscribe 中时,我可以按要求显示数据。但这不是我要找的。我需要在我的 page.ts .
上执行 .subscribe 之外的计算
我见过很多类似的问题,但我似乎找不到解决方案。
这是我的 Typescript 服务文件
export interface Place{
title: string;
type: string;
latitude: number;
longitude: number;
}
export class PlaceService {
placess: Place[];
place: Place;
private placesCollection: AngularFirestoreCollection<Place>;
private places: Observable<Place[]>;
constructor(db: AngularFirestore) {
this.placesCollection = db.collection<Place>('places');
this.places = this.placesCollection.snapshotChanges().pipe(
map(actions =>{
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return{ id, ...data};
});
})
);
}
getPlaces() {
return this.places;
}
}
以及我页面中的相关部分typescript
import { PlaceService, Place } from '../services/place.service';
places: Place[];
ngOnInit() {
this.placeService.getPlaces()
.subscribe(res =>{
this.places = res;
console.log(this.places[0].title);//WORKS
});
console.log(this.places[0].title);//FAILED
}
我收到以下错误消息:
MapPage_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property '0' of undefined
.subscribe 方法必须完成(ajax 请求必须是 200-OK),在 subscribe 方法中你可以存储到你的局部变量中,然后进一步修改是可能的。
您不能使用没有数据的变量。
this.placeService.getPlaces()
.subscribe(res =>{
this.places = res;
});
将需要几秒钟来完成 ajax 调用并获取响应并存储在 "Places" 中。
解决方法(不推荐)使用 set timeout function
等待至少 2 秒。增加秒数,直到找到完成请求和响应的最短秒数。
然后你可以对this.places
做一些计算。
您的问题是您的代码按照您编写的方式运行。当页面初始化时,调用 ngOnInit
。在代码内部转到第一个元素 (this.placeService.getPlaces() ... ) 并立即转到第二个元素 (console.log(this.places[0])。这会引发错误,因为places
变量尚未在您调用 placeService 时设置,目前为 undefined
.
ngOnInit() {
this.placeService.getPlaces() // called first
.subscribe(res =>{
this.places = res;
console.log(this.places[0].title);
});
console.log(this.places[0].title); // called second (undefined error)
}
如果您在设置 places
变量后调用一个函数,第二个 console.log() 将起作用。
ngOnInit() {
this.placeService.getPlaces()
.subscribe(res =>{
this.places = res;
console.log(this.places[0].title);
this.showFirstTitle(); // this.places is set
});
}
showFirstTitle() {
console.log(this.places[0].title); // will work
}
我是 typescript/ionic 4 的新手。我正在尝试访问存储在 firebase 中的数据并在我的打字稿文件中使用它。在 .subscribe 中时,我可以按要求显示数据。但这不是我要找的。我需要在我的 page.ts .
上执行 .subscribe 之外的计算我见过很多类似的问题,但我似乎找不到解决方案。
这是我的 Typescript 服务文件
export interface Place{
title: string;
type: string;
latitude: number;
longitude: number;
}
export class PlaceService {
placess: Place[];
place: Place;
private placesCollection: AngularFirestoreCollection<Place>;
private places: Observable<Place[]>;
constructor(db: AngularFirestore) {
this.placesCollection = db.collection<Place>('places');
this.places = this.placesCollection.snapshotChanges().pipe(
map(actions =>{
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return{ id, ...data};
});
})
);
}
getPlaces() {
return this.places;
}
}
以及我页面中的相关部分typescript
import { PlaceService, Place } from '../services/place.service';
places: Place[];
ngOnInit() {
this.placeService.getPlaces()
.subscribe(res =>{
this.places = res;
console.log(this.places[0].title);//WORKS
});
console.log(this.places[0].title);//FAILED
}
我收到以下错误消息:
MapPage_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property '0' of undefined
.subscribe 方法必须完成(ajax 请求必须是 200-OK),在 subscribe 方法中你可以存储到你的局部变量中,然后进一步修改是可能的。
您不能使用没有数据的变量。
this.placeService.getPlaces()
.subscribe(res =>{
this.places = res;
});
将需要几秒钟来完成 ajax 调用并获取响应并存储在 "Places" 中。
解决方法(不推荐)使用 set timeout function
等待至少 2 秒。增加秒数,直到找到完成请求和响应的最短秒数。
然后你可以对this.places
做一些计算。
您的问题是您的代码按照您编写的方式运行。当页面初始化时,调用 ngOnInit
。在代码内部转到第一个元素 (this.placeService.getPlaces() ... ) 并立即转到第二个元素 (console.log(this.places[0])。这会引发错误,因为places
变量尚未在您调用 placeService 时设置,目前为 undefined
.
ngOnInit() {
this.placeService.getPlaces() // called first
.subscribe(res =>{
this.places = res;
console.log(this.places[0].title);
});
console.log(this.places[0].title); // called second (undefined error)
}
如果您在设置 places
变量后调用一个函数,第二个 console.log() 将起作用。
ngOnInit() {
this.placeService.getPlaces()
.subscribe(res =>{
this.places = res;
console.log(this.places[0].title);
this.showFirstTitle(); // this.places is set
});
}
showFirstTitle() {
console.log(this.places[0].title); // will work
}