UNPKG

hy-push-state

Version:

Turn static web sites into dynamic web apps

81 lines (71 loc) 3.21 kB
// # src / mixin / fetching.js // Copyright (c) 2018 Florian Klampfer <https://qwtel.com/> // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // ## Overview // This file contains helper functions related to fetching new content. // ## Imports import { of, zip } from "rxjs/_esm5"; import { ajax } from "rxjs/_esm5/ajax"; import { catchError, map, take } from "rxjs/_esm5/operators"; import { isExternal } from "../common"; export const fetchMixin = C => class extends C { // ## Fetching makeRequest(context) { return ajax({ method: "GET", responseType: "text", url: context.url, crossDomain: isExternal(this), headers: { Accept: "text/html" }, }).pipe( map(({ response }) => Object.assign(context, { response })), catchError(error => this.recoverIfResponse(context, error)) ); } // The `ajax` method will throw when it encoutners an a 400+ status code, // however these are still valid responses from the server that can be shown using this component. // This assumes error pages have the same HTML strcuture as the other pages though. recoverIfResponse(context, error) { const { status, xhr } = error; // If we have a response, recover and continue with the pipeline. // HACK: Letting ~~servers~~ service workers respond with 598 to force a network error on the component. if (xhr && xhr.response && status > 400 && status < 598) { return of(Object.assign(context, { response: xhr.response })); } // If we don't have a response, this is an acutal error that should be dealt with. return of(Object.assign(context, { error })); } // This function returns the request that matches a given URL. // The way the pipeline is set up, // it is either the `latestPrefetch` value (when the request is already completed), // or the next value on the prefetch observable (when still in progress). getFetch$({ url: { href } }, latestPrefetch, prefetch$) { return href === latestPrefetch.url.href && latestPrefetch.error == null ? of(latestPrefetch) : prefetch$.pipe(take(1)); } // Returns an observable that emits exactly one notice, which contains the response. // It will not emit until an (optional) page transition animation completes. getResponse(prefetch$, [context, latestPrefetch]) { return zip( this.getFetch$(context, latestPrefetch, prefetch$).pipe( map(fetch => Object.assign(fetch, context)) ), this.animPromise, x => x ); } };