source: trip-planner-front/node_modules/rxjs/src/internal/observable/dom/fetch.ts@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 5.8 KB
Line 
1import { Observable } from '../../Observable';
2import { Subscription } from '../../Subscription';
3import { from } from '../../observable/from';
4import { ObservableInput } from '../../types';
5
6export function fromFetch<T>(
7 input: string | Request,
8 init: RequestInit & {
9 selector: (response: Response) => ObservableInput<T>
10 }
11): Observable<T>;
12
13export function fromFetch(
14 input: string | Request,
15 init?: RequestInit
16): Observable<Response>;
17
18/**
19 * Uses [the Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to
20 * make an HTTP request.
21 *
22 * **WARNING** Parts of the fetch API are still experimental. `AbortController` is
23 * required for this implementation to work and use cancellation appropriately.
24 *
25 * Will automatically set up an internal [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
26 * in order to teardown the internal `fetch` when the subscription tears down.
27 *
28 * If a `signal` is provided via the `init` argument, it will behave like it usually does with
29 * `fetch`. If the provided `signal` aborts, the error that `fetch` normally rejects with
30 * in that scenario will be emitted as an error from the observable.
31 *
32 * ### Basic Use
33 *
34 * ```ts
35 * import { of } from 'rxjs';
36 * import { fromFetch } from 'rxjs/fetch';
37 * import { switchMap, catchError } from 'rxjs/operators';
38 *
39 * const data$ = fromFetch('https://api.github.com/users?per_page=5').pipe(
40 * switchMap(response => {
41 * if (response.ok) {
42 * // OK return data
43 * return response.json();
44 * } else {
45 * // Server is returning a status requiring the client to try something else.
46 * return of({ error: true, message: `Error ${response.status}` });
47 * }
48 * }),
49 * catchError(err => {
50 * // Network or other error, handle appropriately
51 * console.error(err);
52 * return of({ error: true, message: err.message })
53 * })
54 * );
55 *
56 * data$.subscribe({
57 * next: result => console.log(result),
58 * complete: () => console.log('done')
59 * });
60 * ```
61 *
62 * ### Use with Chunked Transfer Encoding
63 *
64 * With HTTP responses that use [chunked transfer encoding](https://tools.ietf.org/html/rfc7230#section-3.3.1),
65 * the promise returned by `fetch` will resolve as soon as the response's headers are
66 * received.
67 *
68 * That means the `fromFetch` observable will emit a `Response` - and will
69 * then complete - before the body is received. When one of the methods on the
70 * `Response` - like `text()` or `json()` - is called, the returned promise will not
71 * resolve until the entire body has been received. Unsubscribing from any observable
72 * that uses the promise as an observable input will not abort the request.
73 *
74 * To facilitate aborting the retrieval of responses that use chunked transfer encoding,
75 * a `selector` can be specified via the `init` parameter:
76 *
77 * ```ts
78 * import { of } from 'rxjs';
79 * import { fromFetch } from 'rxjs/fetch';
80 *
81 * const data$ = fromFetch('https://api.github.com/users?per_page=5', {
82 * selector: response => response.json()
83 * });
84 *
85 * data$.subscribe({
86 * next: result => console.log(result),
87 * complete: () => console.log('done')
88 * });
89 * ```
90 *
91 * @param input The resource you would like to fetch. Can be a url or a request object.
92 * @param init A configuration object for the fetch.
93 * [See MDN for more details](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
94 * @returns An Observable, that when subscribed to performs an HTTP request using the native `fetch`
95 * function. The {@link Subscription} is tied to an `AbortController` for the the fetch.
96 */
97export function fromFetch<T>(
98 input: string | Request,
99 initWithSelector: RequestInit & {
100 selector?: (response: Response) => ObservableInput<T>
101 } = {}
102): Observable<Response | T> {
103 const { selector, ...init } = initWithSelector;
104 return new Observable<Response | T>(subscriber => {
105 const controller = new AbortController();
106 const signal = controller.signal;
107 let abortable = true;
108 let unsubscribed = false;
109
110 const subscription = new Subscription();
111 subscription.add(() => {
112 unsubscribed = true;
113 if (abortable) {
114 controller.abort();
115 }
116 });
117
118 let perSubscriberInit: RequestInit;
119 if (init) {
120 // If a signal is provided, just have it teardown. It's a cancellation token, basically.
121 if (init.signal) {
122 if (init.signal.aborted) {
123 controller.abort();
124 } else {
125 const outerSignal = init.signal;
126 const outerSignalHandler = () => {
127 if (!signal.aborted) {
128 controller.abort();
129 }
130 };
131 outerSignal.addEventListener('abort', outerSignalHandler);
132 subscription.add(() => outerSignal.removeEventListener('abort', outerSignalHandler));
133 }
134 }
135 // init cannot be mutated or reassigned as it's closed over by the
136 // subscriber callback and is shared between subscribers.
137 perSubscriberInit = { ...init, signal };
138 } else {
139 perSubscriberInit = { signal };
140 }
141
142 fetch(input, perSubscriberInit).then(response => {
143 if (selector) {
144 subscription.add(from(selector(response)).subscribe(
145 value => subscriber.next(value),
146 err => {
147 abortable = false;
148 if (!unsubscribed) {
149 // Only forward the error if it wasn't an abort.
150 subscriber.error(err);
151 }
152 },
153 () => {
154 abortable = false;
155 subscriber.complete();
156 }
157 ));
158 } else {
159 abortable = false;
160 subscriber.next(response);
161 subscriber.complete();
162 }
163 }).catch(err => {
164 abortable = false;
165 if (!unsubscribed) {
166 // Only forward the error if it wasn't an abort.
167 subscriber.error(err);
168 }
169 });
170
171 return subscription;
172 });
173}
Note: See TracBrowser for help on using the repository browser.