Reputation: 11599
How can I convert whatever Fetch API returns to RxJS Observable? Does RxJS.fromPromise help?
Upvotes: 22
Views: 30583
Reputation: 1653
With observables it's recommended to make a fetch cancelable:
function fetch$(url:string, options:RequestInit) {
return new Observable<Response>(subscriber => {
const controller = new AbortController();
options.signal = controller.signal;
fetch(url, options)
.then(res => {
subscriber.next(res);
subscriber.complete();
})
.catch(er => subscriber.error(er));
return () => { // <- return the observable teardown function
controller.abort();
}
})
}
See https://davidwalsh.name/cancel-fetch
Upvotes: 2
Reputation: 5090
In my case, I used fromFetch:
import { fromFetch } from 'rxjs/fetch';
import { tap } from 'rxjs/operators';
const fetch$ = <T>(url: string, body: T) => fromFetch(url, {
method: 'POST',
mode: 'cors',
credentials: 'include',
body: JSON.stringify(body),
selector: (response) => response.json(),
}).pipe(tap(data => console.log('result:', data)));
fetch$('https://example.com', { somePayload: 123 }).subscribe({
next: result => console.log(result),
complete: () => console.log('done')
});
Upvotes: 3
Reputation: 245
I am using rxjs 6.5.3. I am using below example to convert Fetch API response to RxJS Observable.
const { from } = rxjs;
const { map, switchMap } = rxjs.operators
const observable = from(fetch('data/user.json')).pipe(
switchMap(response => response.json())
)
observable.subscribe(function(result){
console.log('result', result);
});
You can also use fromFetch of rxjs. But fetch API are still experimental.
Upvotes: 7
Reputation: 1488
Using rxjs 6.4 you can use the from operator
See this link: https://www.learnrxjs.io/operators/creation/from.html
Example is in TS:
public getModelDetails(): Observable<YourType> {
const apiCall = fetch(`yourURL/modelDetails`)
.then(response => response.json())
.then(responseJson => {
return responseJson as YourType
})
return from(apiCall)
}
Upvotes: 4
Reputation: 5164
As fetch call returns yet another promise containing the response object, I'd go with creating your own observable:
import { Observable } from 'rxjs';
const data$ = Observable.create(observer => {
fetch('http://server.com')
.then(response => response.json()) // or text() or blob() etc.
.then(data => {
observer.next(data);
observer.complete();
})
.catch(err => observer.error(err));
});
data$.subscribe(data => /*do something with data*/);
Upvotes: 47
Reputation: 301
I'm using rxjs@6.
The operator that accepts observables(like flatMap
, switchMap
, etc...) can also accept promise.
it's very simple as follows.
somethingObservable.pipe(
flatMap(() => fetch('http://some.api.com/post/1')),
subscribe((response) => {
console.log(response);
}),
)
Upvotes: 8
Reputation: 1647
There exist libary rxjs-fetch, but I would suggest not to use it, and write instead:
const getData = (url, params) => {
return fetch(url, params).then(r => {
return r.ok ? r.text() : Promise.reject(`${r.statusText} ${r.status}`)
})
}
const getDataObserver = (url, params) => Rx.Observable.fromPromise(getData())
(in NodeJS you will require node-fetch)
Upvotes: 2