serviceworker-cookbook/render-store/pokemon.js

94 строки
3.5 KiB
JavaScript

// Modern browsers prevent mixed content. I.e., if the page is served from
// a safe (https) origin, they will block the content from other (non https)
// origins. We use this service to tunnel Pokemon API responses through a
// secure origin.
var PROXY = 'https://crossorigin.me/';
// Some times we want to measure.
var startTime = performance.now();
var interpolationTime = 0;
var fetchingModelTime = 0;
// Here is the idea. This is the template for a Pokemon. It is
// in charge of parsing which Pokemon is requested from the querystring
// of the URL, fetch that pokemon and fill the template. Once the template
// has been filled, we are going to mark the document as cached and send
// to the render-store by sending the contents to the service worker.
// The cached mark is a simple `data-*` property in the document element.
var isCached = document.documentElement.dataset.cached;
if (isCached) {
// If cached, log the times and we are done.
logTime();
} else {
// If not, fetch the pokemon info, fill the character sheet, log times and cache.
var pokemonId = getPokemonId();
getPokemon(pokemonId).then(fillCharSheet).then(logTime).then(cache);
}
// Extract the pokemon id from the querystring.
function getPokemonId() {
return window.location.search.split('=')[1];
}
// Fetch pokemon's info as JSON.
function getPokemon(id) {
var fetchingModelStart = performance.now();
var url = PROXY + 'http://pokeapi.co/api/v1/pokemon/' + id + '/?_b=' + Date.now();
return fetch(url).then(function(response) {
fetchingModelTime = performance.now() - fetchingModelStart;
return response.json();
});
}
// Take the contents of the body as template and interpolate with
// the pokemon info.
function fillCharSheet(pokemon) {
var element = document.querySelector('body');
element.innerHTML = interpolateTemplate(element.innerHTML, pokemon);
// Specifically for the cookbook site :(
document.querySelector('img').onload = function() {
if (window.parent === window) {
return;
}
window.parent.document.body.dispatchEvent(new CustomEvent('iframeresize'));
};
}
// Log times for interpolation, fetching and total loading times.
function logTime() {
var loadingTimeLabel = document.querySelector('#loading-time-label');
var interpolationTimeLabel =
document.querySelector('#interpolation-time-label');
var fetchingModelTimeLabel = document.querySelector('#fetching-time-label');
loadingTimeLabel.textContent = (performance.now() - startTime) + ' ms';
interpolationTimeLabel.textContent = interpolationTime + ' ms';
fetchingModelTimeLabel.textContent = fetchingModelTime + ' ms';
}
// Mark the documents as cached, then gets all the HTML content and send to
// the service worker using a `PUT` request into `./render-store/` URL.
// You could be wondering we need to send the URL for the cached content
// but this info is implicitly added as the `referrer` property of the
// request.
function cache() {
document.documentElement.dataset.cached = true;
var data = document.documentElement.outerHTML;
fetch('./render-store/', { method: 'PUT', body: data }).then(function() {
console.log('Page cached');
});
}
// Look for `{{key}}` fragments inside the template and replace them with
// the values of `pokemon[key]`.
function interpolateTemplate(template, pokemon) {
var interpolationStart = performance.now();
var result = template.replace(/{{(\w+)}}/g, function(match, field) {
return pokemon[field];
});
interpolationTime = performance.now() - interpolationStart;
return result;
}