Я борюсь с этой проблемой уже пару дней и не могу двигаться дальше.
Я пытаюсь имитировать базу данных, используя некоторые исходные файлы 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()
в моем сервисе и подписаться на Observable, который возвращает мой метод, а затем использовать список A
, которые я создаю в subscribe()
.
Я не могу заставить это работать. Я пробовал много вещей, возможно, наиболее интуитивно понятным из них является:
// 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 };
}
);
}
}
Обратные вызовы subscribe()
в ngOnInit()
никогда не выполняются. Я пробовал различные комбинации сопоставления, подписки, преобразования в обещания и ругательства, и я не могу ничего лучше, чем ngOnInit()
никогда ничего не делать или запрашивать базу данных в памяти для возврата 404.
Я знаю, что документация forkJoin()
предупреждает, что все Observables должны быть возвращены, прежде чем они будут выдавать какие-либо значения, но, насколько я могу судить, два вызова http.get()
должны возвращаться, если оберточная сантехника подписывается на них. Следующий код успешно регистрирует ожидаемую базу данных (но генерирует ошибку 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
Что мне не хватает, чтобы эта работа работала? Кроме того, это действительно сложно, или я упускаю что-то очевидное?