Buckets:
| import { createOperatorSubscriber } from '../../operators/OperatorSubscriber'; | |
| import { Observable } from '../../Observable'; | |
| import { innerFrom } from '../../observable/innerFrom'; | |
| import { ObservableInput } from '../../types'; | |
| export function fromFetch<T>( | |
| input: string | Request, | |
| init: RequestInit & { | |
| selector: (response: Response) => ObservableInput<T>; | |
| } | |
| ): Observable<T>; | |
| export function fromFetch(input: string | Request, init?: RequestInit): Observable<Response>; | |
| /** | |
| * Uses [the Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to | |
| * make an HTTP request. | |
| * | |
| * **WARNING** Parts of the fetch API are still experimental. `AbortController` is | |
| * required for this implementation to work and use cancellation appropriately. | |
| * | |
| * Will automatically set up an internal [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) | |
| * in order to finalize the internal `fetch` when the subscription tears down. | |
| * | |
| * If a `signal` is provided via the `init` argument, it will behave like it usually does with | |
| * `fetch`. If the provided `signal` aborts, the error that `fetch` normally rejects with | |
| * in that scenario will be emitted as an error from the observable. | |
| * | |
| * ## Examples | |
| * | |
| * Basic use | |
| * | |
| * ```ts | |
| * import { fromFetch } from 'rxjs/fetch'; | |
| * import { switchMap, of, catchError } from 'rxjs'; | |
| * | |
| * const data$ = fromFetch('https://api.github.com/users?per_page=5').pipe( | |
| * switchMap(response => { | |
| * if (response.ok) { | |
| * // OK return data | |
| * return response.json(); | |
| * } else { | |
| * // Server is returning a status requiring the client to try something else. | |
| * return of({ error: true, message: `Error ${ response.status }` }); | |
| * } | |
| * }), | |
| * catchError(err => { | |
| * // Network or other error, handle appropriately | |
| * console.error(err); | |
| * return of({ error: true, message: err.message }) | |
| * }) | |
| * ); | |
| * | |
| * data$.subscribe({ | |
| * next: result => console.log(result), | |
| * complete: () => console.log('done') | |
| * }); | |
| * ``` | |
| * | |
| * ### Use with Chunked Transfer Encoding | |
| * | |
| * With HTTP responses that use [chunked transfer encoding](https://tools.ietf.org/html/rfc7230#section-3.3.1), | |
| * the promise returned by `fetch` will resolve as soon as the response's headers are | |
| * received. | |
| * | |
| * That means the `fromFetch` observable will emit a `Response` - and will | |
| * then complete - before the body is received. When one of the methods on the | |
| * `Response` - like `text()` or `json()` - is called, the returned promise will not | |
| * resolve until the entire body has been received. Unsubscribing from any observable | |
| * that uses the promise as an observable input will not abort the request. | |
| * | |
| * To facilitate aborting the retrieval of responses that use chunked transfer encoding, | |
| * a `selector` can be specified via the `init` parameter: | |
| * | |
| * ```ts | |
| * import { of } from 'rxjs'; | |
| * import { fromFetch } from 'rxjs/fetch'; | |
| * | |
| * const data$ = fromFetch('https://api.github.com/users?per_page=5', { | |
| * selector: response => response.json() | |
| * }); | |
| * | |
| * data$.subscribe({ | |
| * next: result => console.log(result), | |
| * complete: () => console.log('done') | |
| * }); | |
| * ``` | |
| * | |
| * @param input The resource you would like to fetch. Can be a url or a request object. | |
| * @param initWithSelector A configuration object for the fetch. | |
| * [See MDN for more details](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) | |
| * @returns An Observable, that when subscribed to, performs an HTTP request using the native `fetch` | |
| * function. The {@link Subscription} is tied to an `AbortController` for the fetch. | |
| */ | |
| export function fromFetch<T>( | |
| input: string | Request, | |
| initWithSelector: RequestInit & { | |
| selector?: (response: Response) => ObservableInput<T>; | |
| } = {} | |
| ): Observable<Response | T> { | |
| const { selector, ...init } = initWithSelector; | |
| return new Observable<Response | T>((subscriber) => { | |
| // Our controller for aborting this fetch. | |
| // Any externally provided AbortSignal will have to call | |
| // abort on this controller when signaled, because the | |
| // signal from this controller is what is being passed to `fetch`. | |
| const controller = new AbortController(); | |
| const { signal } = controller; | |
| // This flag exists to make sure we don't `abort()` the fetch upon tearing down | |
| // this observable after emitting a Response. Aborting in such circumstances | |
| // would also abort subsequent methods - like `json()` - that could be called | |
| // on the Response. Consider: `fromFetch().pipe(take(1), mergeMap(res => res.json()))` | |
| let abortable = true; | |
| // If the user provided an init configuration object, | |
| // let's process it and chain our abort signals, if necessary. | |
| // If a signal is provided, just have it finalized. It's a cancellation token, basically. | |
| const { signal: outerSignal } = init; | |
| if (outerSignal) { | |
| if (outerSignal.aborted) { | |
| controller.abort(); | |
| } else { | |
| // We got an AbortSignal from the arguments passed into `fromFetch`. | |
| // We need to wire up our AbortController to abort when this signal aborts. | |
| const outerSignalHandler = () => { | |
| if (!signal.aborted) { | |
| controller.abort(); | |
| } | |
| }; | |
| outerSignal.addEventListener('abort', outerSignalHandler); | |
| subscriber.add(() => outerSignal.removeEventListener('abort', outerSignalHandler)); | |
| } | |
| } | |
| // The initialization object passed to `fetch` as the second | |
| // argument. This ferries in important information, including our | |
| // AbortSignal. Create a new init, so we don't accidentally mutate the | |
| // passed init, or reassign it. This is because the init passed in | |
| // is shared between each subscription to the result. | |
| const perSubscriberInit: RequestInit = { ...init, signal }; | |
| const handleError = (err: any) => { | |
| abortable = false; | |
| subscriber.error(err); | |
| }; | |
| fetch(input, perSubscriberInit) | |
| .then((response) => { | |
| if (selector) { | |
| // If we have a selector function, use it to project our response. | |
| // Note that any error that comes from our selector will be | |
| // sent to the promise `catch` below and handled. | |
| innerFrom(selector(response)).subscribe( | |
| createOperatorSubscriber( | |
| subscriber, | |
| // Values are passed through to the subscriber | |
| undefined, | |
| // The projected response is complete. | |
| () => { | |
| abortable = false; | |
| subscriber.complete(); | |
| }, | |
| handleError | |
| ) | |
| ); | |
| } else { | |
| abortable = false; | |
| subscriber.next(response); | |
| subscriber.complete(); | |
| } | |
| }) | |
| .catch(handleError); | |
| return () => { | |
| if (abortable) { | |
| controller.abort(); | |
| } | |
| }; | |
| }); | |
| } | |
Xet Storage Details
- Size:
- 6.96 kB
- Xet hash:
- ff74734fa2d17bf47dfe7bbc31353f5959fc8df926059f0357a03decc7ac9362
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.