В настоящее время я пытаюсь преобразовать старые добрые $ http Promise в rxJs наблюдаемые в angular2.
Очень простой пример того, что я часто делал в угловом 1:
// Some Factory in Angular 1
var somethings = [];
var service = {
all: all
};
return service;
function all() {
return $http
.get('api/somethings')
.then(function(response) {
somethings = parseSomethings(response.data);
return somethings;
});
}
// Some Controller in Angular 1
var vm = this;
vm.somethings = [];
vm.loading = true;
loadThings();
function loadThings() {
SomeFactory
.all()
.then(function(somethings) {
vm.somethings = somethings;
})
.finally(function() {
vm.loading = false;
})
}
Теперь я могу добиться чего-то подобного с угловым2, используя RxJs Observable и Subject. Но я не уверен, как вернуть "завершающие крюки" до вызывающего. (Например: загрузка в угловом контроллере)
То, что я пробовал для angular2, - это нечто похожее:
// Some Service in Angular 2
export class SomeService {
private _somethings$: Subject<Something[]>;
private dataStore: {
somethings: Something[]
};
constructor(private http: Http) {}
get _somethings$() : Observable<Something[]> {
return this._somethings$.asObservable();
}
loadAll() {
this.http
.get('api/somethings')
.map(response => response.json())
.subscribe(
response => {
this.dataStore.somethings = parseSomethings(response.data);
this._somethings$.next(this.dataStore.somethings);
}
);
}
}
//Some Component in Angular 2
export class SomeComponent() {
constructor(private someService: SomeService) {}
ngOnInit() {
this.someService.loadAll();
this.somethings = this.someService.somethings$;
}
}
Заметка
Я использовал тему/Наблюдаемый здесь, чтобы при создании/обновлении/удалении "что-то" я могу позвонить.next, чтобы уведомить подписчиков.
Например:
create(something: Something) : Observable<Something>{
return this.http.post('api/somethings', JSON.stringify(something))
.map(response => response.json())
.do(
something => {
this.dataStore.somethings.push(something);
this._somethings$.next(this.dataStore.somethings); //Notify the subscribers
}
);
}
Заметка
Здесь я использовал.do в методе и при вызове метода в "компоненте формы" я подписываюсь только для получения обработчика завершения:
this.someService.create(something).subscribe(
(ok) => ...
(error) => ...
() => stop loading indicator
)
Вопросов
Ваш последний пример кода в порядке. Просто используйте map()
вместо subscribe()
и подписаться на сайте вызова.
Вы можете использовать
return http.post(...).toPromise(val => ...))
или же
return http.post(...).map(...).toPromise(val => ...))
чтобы получить такое же поведение, как в Angular, где вы можете связать последующие вызовы с помощью .then(...)
map()
, пересылается подписчику. Если вы не хотите изменять значение, а вызываете только некоторые побочные эффекты для каждого события, то с do()
все в порядке.
get
завершает установкуloading
на false? В этом случае переместите блокsubscribe
в вашем сервисе на свой компонент и установите там флагloading
.