在Angular2组件中,我订阅activatedRoute
并使用其中一个路由参数,发出HTTP get
请求。
我似乎需要同时订阅activatedRoute.params
和http.get
Observables - 后者嵌套在前者中。
实际上,我正在嵌套我的订阅,我相信它可以(并且应该)被夷为平地。
我相信我可以使用RxJs,但我不是专家!
以下组件有效,但我相信可以改进。非常感谢您的建议!
import { Component, OnInit } from '@angular/core';
import { Http, Response } from '@angular/http';
import { ActivatedRoute } from '@angular/router';
import {
AngularFireDatabase,
FirebaseListObservable
} from 'angularfire2/database';
import * as firebase from 'firebase/app';
import { GridService } from '../grid.service';
import { SquareMetadata } from '../square-metadata';
import { SquareService } from '../square.service';
@Component({
selector: 'pu-grid',
templateUrl: './grid.component.html',
styleUrls: ['./grid.component.scss']
})
export class GridComponent implements OnInit {
public list: FirebaseListObservable<SquareMetadata[]>;
constructor(
private activatedRoute: ActivatedRoute,
private gridService: GridService,
private http: Http,
private squareService: SquareService
) {}
ngOnInit() {
this.activatedRoute.params.subscribe((params) => {
this.http.get('https://pu2-dev.firebaseio.com/squareMetadata/' + params.key + '.json?shallow=true')
.map((response: Response) => {
return response.json();
})
.subscribe((keys: Array<string>) => {
console.log(keys);
}, (error) => {
console.log(error);
});
this.gridService.activatedGrid = params.key;
this.list = this.squareService.list;
});
}
}
我已根据 atomrc&#39> 回答重构了我的ngOnInit
函数,但我现在收到错误,导航到使用此组件的路径时应用程序失败。
到目前为止,这是我的重构:
ngOnInit() {
this.activatedRoute.params.mergeMap((params: Params) => {
return this.http.get('https://pu2-dev.firebaseio.com/squareMetadata/-KnGq1D89F4pdCH_vjhs.json?shallow=true')
})
.map((response: Response) => {
return response.json();
})
.subscribe((keys: Array<string>) => {
console.log(keys);
}, (error) => {
console.log(error);
});
}
我收到错误:
Error: Uncaught (in promise): TypeError: undefined is not a function (near '....map(function (response)...')
此外,如果您在我的原始代码中注意到activatedRoute.params
订阅的底部,我有this.gridService.activatedGrid = params.key;
行
在重构中,这需要进入订阅成功回调。但params.key
在那里无法使用。
因此,我认为这不是我所追求的解决方案。
到目前为止,感谢您的帮助!
为了将来参考,以下是我的工作重构:
import { Component, OnInit } from '@angular/core';
import { Http, Response } from '@angular/http';
import { ActivatedRoute, Params, Router } from '@angular/router';
import {
AngularFireDatabase,
FirebaseListObservable
} from 'angularfire2/database';
import * as firebase from 'firebase/app';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import { GridService } from '../grid.service';
import { Shallow } from '../shallow';
import { SquareMetadata } from '../square-metadata';
import { SquareService } from '../square.service';
import { environment } from '../../environments/environment';
@Component({
selector: 'pu-grid',
templateUrl: './grid.component.html',
styleUrls: ['./grid.component.scss']
})
export class GridComponent implements OnInit {
public list: FirebaseListObservable<SquareMetadata[]>;
constructor(
private activatedRoute: ActivatedRoute,
private gridService: GridService,
private http: Http,
private router: Router,
private squareService: SquareService
) {}
ngOnInit() {
this.activatedRoute.params.mergeMap((params: Params) => {
let path: string = [
environment.firebaseAppConfig.databaseURL,
'squareMetadata',
params.key
].join('/');
return this.http.get([ path, '.json?shallow=true' ].join(''))
.map((response: Response) => {
return response.json();
})
.map((json: Shallow) => {
return { key: params.key, json: json };
});
})
.subscribe(({ key, json }: { key: string, json: Shallow }) => {
if (json) {
this.gridService.activatedGrid = key;
this.list = this.squareService.list;
} else {
this.router.navigate([ '' ]);
}
}, (error: Error) => {
throw new Error(error.message);
});
}
}
答案 0 :(得分:2)
你是完全正确的,扁平化是这里要做的事情:)
使用rxjs,您要查找的运算符为mergeMap
。
这是你可以做的
this.activatedRoute.params
.mergeMap((params) => {
return this.http.get('https://example.com/' + params.key)
.map(response => response.json())
// build a new object from the response's data and the params
.map(data => ({ params: params, data: data }))
})
.subscribe(({ params, data }) => {
this.gridService.activatedGrid = params.key;
// do stuff with `data`
});