Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | 1x 1x | // @ts-check import { forOwn, isNil } from "lodash"; import { mixinMaker } from "../utils"; const RELOAD_INTERVAL = 15 * 60 * 1000; // Check every 15 mins if the page should be reloaded /** * @typedef {{ * reloadInterval?: number, * }} BaseChangeReloadMixinOptions */ const BaseChangeReloadMixin = (/** @type {BaseChangeReloadMixinOptions}*/options) => mixinMaker({ /** Supported options: { reloadInterval: number (def 900 000 (15min)) // The delay between two check requests } */ /** * @returns {{ * intervalHandler: NodeJS.Timeout | undefined, * initialETag: string | undefined, * initialDate: Date | undefined, * checkETag: boolean * }} */ data() { return { intervalHandler: undefined, initialETag: undefined, initialDate: undefined, checkETag: true // if false, fallback on check Date }; }, async mounted() { try { // Trigger reload check only if the file is hosted on a server if (!window.location.href.includes("http")) { console.warn("Website is not hosted on a server. Reload on source change disabled."); return; } // Check for supported reload method (ETage / Date) const response = await this.fetch(window.location.href, { method: "HEAD" }); // Empty => not supported (no comparison availlable) this.initialETag = response.getResponseHeader("ETag"); // Empty => not supported (will always return current date) this.initialDate = response.getResponseHeader("Last-Modified"); // If no server method availlable, cancel the reloading check if (isNil(this.initialETag) && isNil(this.initialDate)) { console.warn("Neither 'ETag' or 'Last-Modified' methods are supported by the server. Reload on source change disabled."); return; } // If Etag is not supported by the server, fallback on Date check if (isNil(this.initialETag)) { console.info("'ETag not supported by the server, fallback on Date check"); this.checkETag = false; } // Initialize the source reload loop this.intervalHandler = setInterval( async () => { await this.checkSource(); }, options.reloadInterval ?? RELOAD_INTERVAL); } catch (error) { console.error(error); } }, beforeDestroy() { clearInterval(this.intervalHandler); }, methods: { /** * Custom fetch to prevent the ETag issue on firfox * @param {string} url * @param {{ method: string, headers?: object }} config * @returns {Promise<any>} request promise */ fetch(url, config) { return new Promise(function(resolve, reject) { const xhr = new XMLHttpRequest(); xhr.open(config.method, url); forOwn(config.headers, (value, name) => xhr.setRequestHeader(name, value)); xhr.onload = () => resolve(xhr); xhr.onerror = (error) => reject(error); xhr.send(); }); }, /** * @returns {Promise<void>} */ async checkSource() { const STATUS_OK = 200; const headers = {}; if (this.checkETag) { // Compare with the ETag fetched at page load headers["If-None-Match"] = this.initialETag; } else { // Compare with last modified date stored at the beginning headers["If-Modified-Since"] = this.initialDate; } // Retrieve information from the sources of the page to see if it should be reloaded const response = await this.fetch(window.location.href, { method: "HEAD", headers }); // Check if the document was modified since load if (response.status === STATUS_OK) { // To avoid inconsistencies between browsers (return OK but different ETag) if (this.checkETag && this.initialETag === response.getResponseHeader("ETag")) { return; } window.location.reload(); // We refresh the page } } } }); export default BaseChangeReloadMixin; |