Angular 4 如何 return 解析器中的多个可观察对象
Angular 4 How to return multiple observables in resolver
如标题所述,我需要 return 多个可观察值或结果。目标基本上是加载图书馆列表,然后根据该图书馆 ID 加载书籍。我不想在组件中调用服务,而是希望在页面加载之前加载所有数据。
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { UserService } from './../_services/index';
@Injectable()
export class LibraryResolver implements Resolve<any> {
constructor(private _userService: UserService) {}
resolve(route: ActivatedRouteSnapshot) {
return this._userService.getLibraryList();
}
}
如何先加载图书馆列表,然后再加载每个图书馆的图书信息和 return 我的组件?
PS:我的服务通过 Id
加载了这个方法
this.userService.getLibraryBooks(this.library["id"]).subscribe((response) => {
// response processing
})
我也有类似的情况,但我的处理方式略有不同。
对于你的情况,我的理解是你想要获取查询参数,然后根据响应,调用更多的服务。
我这样做的方法是让一个组件包裹其他组件,并传递它们需要的对象。我通过路由 paramMap 订阅它们,然后将我所有其他调用包装在一个。 Observalbe.forkJoin
在我的包装器组件中,我执行以下操作:
ngOnInit() {
this.route.params.subscribe((params) => {
if (params.hasOwnProperty('id') && params['id'] != '') {
const slug = params['slug'];
Observable.forkJoin([
this.myService.getData(id),
this.myService.getOtherData(id),
]).subscribe(
([data, otherData]) => {
this.data = data;
this.otherData = otherData;
},
error => {
console.log('An error occurred:', error);
},
() => {
this.loading = false;
}
);
}
});
不完全是您想要的,但我希望它能为您指明正确的方向
我建议您使用 Observables,它们会让您的生活轻松很多。
查看这两篇文章以获取有关如何使用可观察对象实现该目标的更多详细信息:
http://www.syntaxsuccess.com/viewarticle/combining-multiple-rxjs-streams-in-angular-2.0
http://blog.danieleghidoli.it/2016/10/22/http-rxjs-observables-angular/
我个人使用flatMap
祝你好运。
您可以使用 withLatestFrom
轻松解析多个可观察值。
这是 Stackblitz 中的一个工作演示:https://stackblitz.com/edit/angular-xfd5xx
下面的解决方案。
在您的解析器中,使用 withLatestFrom
组合您的可观察对象:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Library } from '../models/library.model';
import { LibraryBook } from '../models/library-book.model';
import { LibraryService } from '../services/library.service';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';
@Injectable()
export class LibraryDisplayResolver implements Resolve<[Library, LibraryBook[]]> {
constructor(
private _libraryService: LibraryService,
) { }
resolve (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<[Library, LibraryBook[]]> {
const libraryId = route.params['id'];
return this._libraryService.getLibrary(libraryId).pipe(
withLatestFrom(
this._libraryService.getBooksFromLibrary(libraryId)
)
);
}
}
确保您的解析器在您的路由中设置了适当的标识符:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LibraryDisplayComponent } from './library-display.component';
import { LibraryDisplayResolver } from '../resolvers/library-display.resolver';
const routes: Routes = [
{
path: ':id',
component: LibraryDisplayComponent,
resolve: {
libraryResolverData: LibraryDisplayResolver
}
},
{
path: '',
redirectTo: '1',
pathMatch: 'full'
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class LibraryDisplayRoutingModule { }
在接收组件中,您可以像这样访问两个可观察对象的快照:
import { Component, OnInit } from '@angular/core';
import { LibraryBook } from '../models/library-book.model';
import { Library } from '../models/library.model';
import { ActivatedRoute } from '@angular/router';
@Component({
// tslint:disable-next-line:component-selector
selector: 'library-display',
templateUrl: './library-display.component.html',
styleUrls: ['./library-display.component.scss']
})
export class LibraryDisplayComponent implements OnInit {
library: Library;
libraryBooks: LibraryBook[];
constructor(
private route: ActivatedRoute
) { }
ngOnInit() {
this.library = this.route.snapshot.data['libraryResolverData'][0];
this.libraryBooks = this.route.snapshot.data['libraryResolverData'][1];
}
}
我找到了这个问题的解决方案,也许会对某些人有所帮助,所以基本上我已经使用 forkJoin
组合多个 Observables 并解决所有问题。
resolve(route: ActivatedRouteSnapshot): Observable<any> {
return forkJoin([
this._elementsService.getElementTypes(),
this._elementsService.getDepartments()
.catch(error => {
/* if(error.status === 404) {
this.router.navigate(['subscription-create']);
} */
return Observable.throw(error);
})
]).map(result => {
return {
types: result[0],
departments: result[1]
};
});
};
现在它可以正常工作,如预期的那样。
resolve(route: ActivatedRouteSnapshot) {
let id = route.params['id'];
const getUser = new Promise((resolve, reject) => {
this.customerService.getSingle(id).subscribe((res) => {
resolve(res);
}, (err) => {
console.log('err', err);
});
});
const getDocument = new Promise((resolve, reject) => {
this.customerService.getDocument().subscribe((res) => {
resolve(res);
});
});
return Promise.all([getUser, getDocument]);
}
如标题所述,我需要 return 多个可观察值或结果。目标基本上是加载图书馆列表,然后根据该图书馆 ID 加载书籍。我不想在组件中调用服务,而是希望在页面加载之前加载所有数据。
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { UserService } from './../_services/index';
@Injectable()
export class LibraryResolver implements Resolve<any> {
constructor(private _userService: UserService) {}
resolve(route: ActivatedRouteSnapshot) {
return this._userService.getLibraryList();
}
}
如何先加载图书馆列表,然后再加载每个图书馆的图书信息和 return 我的组件?
PS:我的服务通过 Id
加载了这个方法this.userService.getLibraryBooks(this.library["id"]).subscribe((response) => {
// response processing
})
我也有类似的情况,但我的处理方式略有不同。
对于你的情况,我的理解是你想要获取查询参数,然后根据响应,调用更多的服务。
我这样做的方法是让一个组件包裹其他组件,并传递它们需要的对象。我通过路由 paramMap 订阅它们,然后将我所有其他调用包装在一个。 Observalbe.forkJoin
在我的包装器组件中,我执行以下操作:
ngOnInit() {
this.route.params.subscribe((params) => {
if (params.hasOwnProperty('id') && params['id'] != '') {
const slug = params['slug'];
Observable.forkJoin([
this.myService.getData(id),
this.myService.getOtherData(id),
]).subscribe(
([data, otherData]) => {
this.data = data;
this.otherData = otherData;
},
error => {
console.log('An error occurred:', error);
},
() => {
this.loading = false;
}
);
}
});
不完全是您想要的,但我希望它能为您指明正确的方向
我建议您使用 Observables,它们会让您的生活轻松很多。 查看这两篇文章以获取有关如何使用可观察对象实现该目标的更多详细信息:
http://www.syntaxsuccess.com/viewarticle/combining-multiple-rxjs-streams-in-angular-2.0
http://blog.danieleghidoli.it/2016/10/22/http-rxjs-observables-angular/
我个人使用flatMap
祝你好运。
您可以使用 withLatestFrom
轻松解析多个可观察值。
这是 Stackblitz 中的一个工作演示:https://stackblitz.com/edit/angular-xfd5xx
下面的解决方案。
在您的解析器中,使用 withLatestFrom
组合您的可观察对象:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Library } from '../models/library.model';
import { LibraryBook } from '../models/library-book.model';
import { LibraryService } from '../services/library.service';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';
@Injectable()
export class LibraryDisplayResolver implements Resolve<[Library, LibraryBook[]]> {
constructor(
private _libraryService: LibraryService,
) { }
resolve (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<[Library, LibraryBook[]]> {
const libraryId = route.params['id'];
return this._libraryService.getLibrary(libraryId).pipe(
withLatestFrom(
this._libraryService.getBooksFromLibrary(libraryId)
)
);
}
}
确保您的解析器在您的路由中设置了适当的标识符:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LibraryDisplayComponent } from './library-display.component';
import { LibraryDisplayResolver } from '../resolvers/library-display.resolver';
const routes: Routes = [
{
path: ':id',
component: LibraryDisplayComponent,
resolve: {
libraryResolverData: LibraryDisplayResolver
}
},
{
path: '',
redirectTo: '1',
pathMatch: 'full'
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class LibraryDisplayRoutingModule { }
在接收组件中,您可以像这样访问两个可观察对象的快照:
import { Component, OnInit } from '@angular/core';
import { LibraryBook } from '../models/library-book.model';
import { Library } from '../models/library.model';
import { ActivatedRoute } from '@angular/router';
@Component({
// tslint:disable-next-line:component-selector
selector: 'library-display',
templateUrl: './library-display.component.html',
styleUrls: ['./library-display.component.scss']
})
export class LibraryDisplayComponent implements OnInit {
library: Library;
libraryBooks: LibraryBook[];
constructor(
private route: ActivatedRoute
) { }
ngOnInit() {
this.library = this.route.snapshot.data['libraryResolverData'][0];
this.libraryBooks = this.route.snapshot.data['libraryResolverData'][1];
}
}
我找到了这个问题的解决方案,也许会对某些人有所帮助,所以基本上我已经使用 forkJoin
组合多个 Observables 并解决所有问题。
resolve(route: ActivatedRouteSnapshot): Observable<any> {
return forkJoin([
this._elementsService.getElementTypes(),
this._elementsService.getDepartments()
.catch(error => {
/* if(error.status === 404) {
this.router.navigate(['subscription-create']);
} */
return Observable.throw(error);
})
]).map(result => {
return {
types: result[0],
departments: result[1]
};
});
};
现在它可以正常工作,如预期的那样。
resolve(route: ActivatedRouteSnapshot) {
let id = route.params['id'];
const getUser = new Promise((resolve, reject) => {
this.customerService.getSingle(id).subscribe((res) => {
resolve(res);
}, (err) => {
console.log('err', err);
});
});
const getDocument = new Promise((resolve, reject) => {
this.customerService.getDocument().subscribe((res) => {
resolve(res);
});
});
return Promise.all([getUser, getDocument]);
}