Angular 4, angular-in-memory-web-api, and Observables: createDb() 返回 Observable 或 Promise 不工作
Angular 4, angular-in-memory-web-api, and Observables: createDb() returning Observable or Promise does not work
这几天一直在和这个问题搏斗,无法前进。
我正在尝试使用一些表示具有外键关系的表的源 JSON 文件来模拟数据库。假设有一个实体 A
和一个实体 B
,其中 A
与 B
具有多对一关系。除了需要一些额外的清理之外,JSON 文件只列出了这些关系的主键,所以我有 DTO 包装器 RawA
和 RawB
,我可以映射到 A
和B
分别得到数据后
我正在使用 angular-in-memory-web-api,所以我设置了 app.module.ts 以使用允许我检索 JSON 文件如下:
HttpClientInMemoryWebApiModule.forRoot(
InMemoryDataService,
{ apiBase: '/api', dataEncapsulation: false, passThruUnknownUrl: true }
)
在我的app.component.ts中,我暂时有一个ngOnInit()
方法来测试这个数据库的构建:
ngOnInit() {
let result = this.http.get('/api/A')
.subscribe(
next => { console.log('next:'); console.log(next); },
error => { console.log('error:'); console.log(error); },
() => console.log('complete')
);
}
据我理解,内存数据库应该看到这个请求,在我的服务上调用createDb()
,并订阅我的方法returns的Observable,然后使用列表我在 subscribe()
.
中创建的 A
个
我无法让它工作。我尝试了很多东西,也许最直观的是:
// most imports omitted, but I am using
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
@Injectable()
export class InMemoryDataService implements InMemoryDbService() {
private static aUrl = './assets/data/a.json';
private static bUrl = './assets/data/b.json';
private http: HttpClient;
constructor( private injector: Injector ) {}
createDb( reqInfo?: RequestInfo ): {} | Observable<{}> | Promise<{}> {
this.http = this.injector.get(HttpClient);
return Observable.forkJoin(
this.http.get<RawA[]>(InMemoryDataService.aUrl),
this.http.get<RawB[]>(InMemoryDataService.bUrl)
).map(
result => {
let bs = (result[1] as RawB[]).map(raw => new B(raw));
let as = (result[0] as RawA[]).map(raw => new A(raw, bs));
return { A: as, B: bs };
}
);
}
}
ngOnInit()
中的 subscribe()
回调从不 运行。我已经尝试了映射、订阅、转换为 Promises 和发誓的各种组合,我没有比 ngOnInit()
从不做任何事情或提示内存数据库 return 404 更好的了。
我知道 forkJoin()
文档警告说所有 Observables 都需要 return 才能产生任何值,但据我所知,这两个 http.get()
调用应该return 如果包装管道订阅了它们。以下代码成功记录了我期望的数据库(但它生成了 404,可能是因为立即调用 api/A 看到了一个空数组):
createDb( reqInfo?: RequestInfo ): {} | Observable<{}> | Promise<{}> {
this.http = this.injector.get(HttpClient);
let database: { A: A[], B: B[] } = { A: [], B: [] };
Observable.forkJoin(
this.http.get<RawA[]>(InMemoryDataService.aUrl),
this.http.get<RawB[]>(InMemoryDataService.bUrl)
).subscribe(
result => {
database.B = (result[1] as RawB[]).map(raw => new B(raw));
database.A = (result[0] as RawA[]).map(raw => new A(raw, database.B));
console.log(database);
return database;
}
);
return database;
}
// console logs {A: Array(100), B: Array(20)}, and inspection shows the field values are all correct
我缺少什么来完成这项工作?另外,这真的很棘手吗,还是我遗漏了一些明显的东西?
创建数据库
查看您的代码:
Observable.forkJoin(
this.http.get<RawA[]>(InMemoryDataService.aUrl),
this.http.get<RawB[]>(InMemoryDataService.bUrl)
).subscribe(
我怀疑,由于您连接了所有 http 请求并且尚未创建 Db,因此这些请求将始终处于等待状态。
为了克服它,我会使用其他东西来获取 json 数据。
例如Fetch API:
createDb( reqInfo?: RequestInfo ): Observable<{}> | Promise<{}> {
this.http = this.injector.get(HttpClient);
return Promise.all([
fetch(InMemoryDataService.aUrl),
fetch(InMemoryDataService.bUrl)
])
.then((result: any) => {
return Promise.all(result.map(x => x.json()));
})
.then(
result => {
const bs = (result[1] as RawB[]).map(raw => new B(raw));
const as = (result[0] as RawA[]).map(raw => new A(raw, bs));
return { A: as, B: bs };
}
);
}
ApiBase
您需要更改的另一件事是 api url
app.module.ts
{ apiBase: 'api/', dataEncapsulation: false, passThruUnknownUrl: true }
^^^^^^
component.ts
let result = this.http.get('api/A')
^^^^^^^^^
或者您可以使用以下配对:
{ apiBase: '/', dataEncapsulation: false, passThruUnknownUrl: true }
let result = this.http.get('/A')
原因是这样 angular-in-web-memory-api
parses your url
这几天一直在和这个问题搏斗,无法前进。
我正在尝试使用一些表示具有外键关系的表的源 JSON 文件来模拟数据库。假设有一个实体 A
和一个实体 B
,其中 A
与 B
具有多对一关系。除了需要一些额外的清理之外,JSON 文件只列出了这些关系的主键,所以我有 DTO 包装器 RawA
和 RawB
,我可以映射到 A
和B
分别得到数据后
我正在使用 angular-in-memory-web-api,所以我设置了 app.module.ts 以使用允许我检索 JSON 文件如下:
HttpClientInMemoryWebApiModule.forRoot(
InMemoryDataService,
{ apiBase: '/api', dataEncapsulation: false, passThruUnknownUrl: true }
)
在我的app.component.ts中,我暂时有一个ngOnInit()
方法来测试这个数据库的构建:
ngOnInit() {
let result = this.http.get('/api/A')
.subscribe(
next => { console.log('next:'); console.log(next); },
error => { console.log('error:'); console.log(error); },
() => console.log('complete')
);
}
据我理解,内存数据库应该看到这个请求,在我的服务上调用createDb()
,并订阅我的方法returns的Observable,然后使用列表我在 subscribe()
.
A
个
我无法让它工作。我尝试了很多东西,也许最直观的是:
// most imports omitted, but I am using
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
@Injectable()
export class InMemoryDataService implements InMemoryDbService() {
private static aUrl = './assets/data/a.json';
private static bUrl = './assets/data/b.json';
private http: HttpClient;
constructor( private injector: Injector ) {}
createDb( reqInfo?: RequestInfo ): {} | Observable<{}> | Promise<{}> {
this.http = this.injector.get(HttpClient);
return Observable.forkJoin(
this.http.get<RawA[]>(InMemoryDataService.aUrl),
this.http.get<RawB[]>(InMemoryDataService.bUrl)
).map(
result => {
let bs = (result[1] as RawB[]).map(raw => new B(raw));
let as = (result[0] as RawA[]).map(raw => new A(raw, bs));
return { A: as, B: bs };
}
);
}
}
ngOnInit()
中的 subscribe()
回调从不 运行。我已经尝试了映射、订阅、转换为 Promises 和发誓的各种组合,我没有比 ngOnInit()
从不做任何事情或提示内存数据库 return 404 更好的了。
我知道 forkJoin()
文档警告说所有 Observables 都需要 return 才能产生任何值,但据我所知,这两个 http.get()
调用应该return 如果包装管道订阅了它们。以下代码成功记录了我期望的数据库(但它生成了 404,可能是因为立即调用 api/A 看到了一个空数组):
createDb( reqInfo?: RequestInfo ): {} | Observable<{}> | Promise<{}> {
this.http = this.injector.get(HttpClient);
let database: { A: A[], B: B[] } = { A: [], B: [] };
Observable.forkJoin(
this.http.get<RawA[]>(InMemoryDataService.aUrl),
this.http.get<RawB[]>(InMemoryDataService.bUrl)
).subscribe(
result => {
database.B = (result[1] as RawB[]).map(raw => new B(raw));
database.A = (result[0] as RawA[]).map(raw => new A(raw, database.B));
console.log(database);
return database;
}
);
return database;
}
// console logs {A: Array(100), B: Array(20)}, and inspection shows the field values are all correct
我缺少什么来完成这项工作?另外,这真的很棘手吗,还是我遗漏了一些明显的东西?
创建数据库
查看您的代码:
Observable.forkJoin(
this.http.get<RawA[]>(InMemoryDataService.aUrl),
this.http.get<RawB[]>(InMemoryDataService.bUrl)
).subscribe(
我怀疑,由于您连接了所有 http 请求并且尚未创建 Db,因此这些请求将始终处于等待状态。
为了克服它,我会使用其他东西来获取 json 数据。
例如Fetch API:
createDb( reqInfo?: RequestInfo ): Observable<{}> | Promise<{}> {
this.http = this.injector.get(HttpClient);
return Promise.all([
fetch(InMemoryDataService.aUrl),
fetch(InMemoryDataService.bUrl)
])
.then((result: any) => {
return Promise.all(result.map(x => x.json()));
})
.then(
result => {
const bs = (result[1] as RawB[]).map(raw => new B(raw));
const as = (result[0] as RawA[]).map(raw => new A(raw, bs));
return { A: as, B: bs };
}
);
}
ApiBase
您需要更改的另一件事是 api url
app.module.ts
{ apiBase: 'api/', dataEncapsulation: false, passThruUnknownUrl: true }
^^^^^^
component.ts
let result = this.http.get('api/A')
^^^^^^^^^
或者您可以使用以下配对:
{ apiBase: '/', dataEncapsulation: false, passThruUnknownUrl: true }
let result = this.http.get('/A')
原因是这样 angular-in-web-memory-api
parses your url