Lisa Kudrow
Libérer: 2025-02-17 11:06:10
original
521 Les gens l'ont consulté

Cache Fetched AJAX Requests Locally: Wrapping the Fetch API

Cet article a été écrit par l'auteur invité Peter Bengtsson. Le post d'invité spécial de SitePoint est conçu pour vous apporter un excellent contenu d'écrivains et de conférenciers bien connus dans la communauté JavaScript

Cet article montre comment implémenter un cache local de demandes récupérées afin que si elle est exécutée à plusieurs reprises, elle sera lue dans le magasin de session. L'avantage est que vous n'avez pas besoin d'écrire de code personnalisé pour chaque ressource que vous souhaitez cache.

Si vous souhaitez montrer votre prochaine fête JavaScript et montrer vos différentes compétences en matière de promesse, des API de pointe et un stockage local, lisez la suite.

gains principaux

  • En utilisant l'API Fetch, les développeurs peuvent créer des caches locales de demandes AJAX, améliorant l'efficacité en réduisant les appels de réseau redondants et en accélérant la récupération des données.
  • Le moyen simple de cache à l'aide de variables globales est limitée par la persistance de session;
  • L'implémentation cachedFetch encapsule les appels standard fetch, qui peuvent automatiquement mettre en cache les réponses en fonction du type de contenu et de l'URL, ce qui rend le mécanisme de cache universel.
  • Les améliorations vers
  • cachedFetch incluent la gestion des tubes de cache à partir du stockage de session avant de faire une demande de réseau, et la gestion du contenu a expiré pour éviter d'utiliser des données obsolètes.
  • Les améliorations futures peuvent inclure le traitement des données binaires et l'utilisation d'URL de hachage comme cache pour optimiser les processus de stockage et de récupération dans les applications Web.

Répondre à l'API

À ce stade, vous devriez être familier avec Fetch. Il s'agit d'une nouvelle API native dans le navigateur pour remplacer l'ancienne API XMLHTTPREQUEST.

Puis-je utiliser Fetch? https://www.php.cn/link/B751EA087892EBECA363034301f45c69 sur le site Web sur le support principal du navigateur pour la fonction Fetch.

Bien que tous les navigateurs ne soient pas parfaitement mis en œuvre, vous pouvez utiliser le polyfill Fetch de GitHub (il y a des spécifications standard ici si vous ne faites rien toute la journée).

Alternatives simples

Supposons que vous sachiez exactement quelle ressource vous devez télécharger et que vous ne souhaitez le télécharger qu'une seule fois. Vous pouvez utiliser les variables globales comme cache comme suit:

let origin = null;
fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(information => {
    origin = information.origin; // 您的客户端IP
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  console.log('您的来源是 ' + origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Exemple de codepen

Cela ne dépend que des variables globales pour contenir des données mises en cache. Le problème direct est que si vous rechargez la page ou naviguez vers une nouvelle page, les données mises en cache disparaîtront.

Avant de disséquer ses lacunes, mettons à niveau la première solution simple.

fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(info => {
    sessionStorage.setItem('information', JSON.stringify(info));
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  let info = JSON.parse(sessionStorage.getItem('information'));
  console.log('您的来源是 ' + info.origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion

Exemple de codepen

Le premier problème direct est que la fetch est basée sur la promesse, ce qui signifie que nous ne pouvons pas déterminer quand cela sera fait, donc par souci de certitude, nous ne devons pas compter sur son exécution jusqu'à ce que ses promesses analysent.

Le deuxième problème est que cette solution est très spécifique aux URL spécifiques et aux extraits de données mis en cache spécifiques (informations clés dans cet exemple). Ce que nous voulons, c'est une solution basée sur une URL universelle.

Première implémentation - Gardez les choses simples

Créons un emballage autour de Fetch qui renvoie également une promesse. Le code qui l'appelle peut ne pas se soucier de savoir si le résultat provient du réseau ou du cache local.

alors imaginez que vous a l'habitude de faire ceci:

let origin = null;
fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(information => {
    origin = information.origin; // 您的客户端IP
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  console.log('您的来源是 ' + origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Exemple de codepen

Maintenant, vous souhaitez l'envelopper afin que les appels de réseau en double puissent bénéficier du cache local. Appelons simplement ça cachedfetch, donc le code ressemble à ceci:

fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(info => {
    sessionStorage.setItem('information', JSON.stringify(info));
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  let info = JSON.parse(sessionStorage.getItem('information'));
  console.log('您的来源是 ' + info.origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
La première fois qu'il s'exécute, il doit analyser la demande sur le réseau et stocker le résultat dans le cache. La deuxième fois doit être extraite directement du stockage local.

Commençons par le code qui enveloppe simplement la fonction de fetch:

fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(issues => {
    console.log('您的来源是 ' + info.origin);
  });
Copier après la connexion
Copier après la connexion

Exemple de codepen

Cela fonctionne, mais bien sûr, cela ne fonctionne pas. Implémentons d'abord le stockage des données extraites.

cachedFetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(info => {
    console.log('您的来源是 ' + info.origin);
  });
Copier après la connexion

Exemple de codepen

Il y a beaucoup à faire ici.

La première promesse renvoyée par Fetch continuera en fait à effectuer la demande GET. S'il y a un problème avec CORS (partage de ressources croisées), les méthodes .text (), .json () ou .blob () ne fonctionneront pas.

La fonctionnalité la plus intéressante est que nous devons

cloner l'objet de réponse renvoyé par la première promesse. Si nous ne le faisons pas, nous nous sur-injectons, et lorsque les utilisateurs finaux de Promise essaient d'appeler .json () (par exemple), ils obtiennent cette erreur:

Une autre chose à noter est la gestion minutieuse du type de réponse: nous ne stockons la réponse que lorsque le code d'état est de 200 et que le type de contenu est l'application / JSON ou le texte / *. En effet, SessionStorage ne peut stocker que du texte.

const cachedFetch = (url, options) => {
  return fetch(url, options);
};
Copier après la connexion
Ce qui suit est un exemple de la façon de l'utiliser:

La chose intelligente à propos de cette solution à ce jour est qu'elle fonctionne sans interférer avec les demandes JSON

et

HTML. Lorsqu'il s'agit d'une image, il n'essaie pas de le stocker dans SessionStorage.

const cachedFetch = (url, options) => {
  // 使用URL作为sessionStorage的缓存键
  let cacheKey = url;
  return fetch(url, options).then(response => {
    // 让我们只在内容类型为JSON或非二进制内容时存储在缓存中
    let ct = response.headers.get('Content-Type');
    if (ct && (ct.match(/application\/json/i) || ct.match(/text\//i))) {
      // 有一个.json()而不是.text(),但我们将它存储在sessionStorage中作为字符串。
      // 如果我们不克隆响应,它将在返回时被使用。这样我们就可以不干扰。
      response.clone().text().then(content => {
        sessionStorage.setItem(cacheKey, content);
      });
    }
    return response;
  });
};
Copier après la connexion
Deuxième implémentation - Retour Cache Retour Hit

Par conséquent, notre première implémentation n'est responsable que du stockage de la réponse de la demande. Cependant, si vous appelez CachedFetch la deuxième fois, il n'essaiera toujours pas de récupérer quoi que ce soit de SessionStorage . Ce que nous devons faire est de retourner une promesse, et la promesse doit analyser un objet de réponse.

Commençons par une implémentation très basique:

Exemple de codepen

ça marche!
<code>TypeError: Body has already been consumed.</code>
Copier après la connexion

Pour voir comment il fonctionne réellement, ouvrez le codep de ce code, puis ouvrez l'onglet "réseau" du navigateur dans les outils du développeur. Appuyez plusieurs fois sur le bouton d'exécution (le coin supérieur droit de Codepen) et vous devriez voir que seules les images demandent à plusieurs reprises sur le réseau.

L'une des intelligences de cette solution est le manque de "pâtes de rappel". Étant donné que l'appel SessionStorage.getItem est synchrone (c'est-à-dire le blocage), nous n'avons pas à traiter "est-ce dans le stockage local?" Et nous ne rendrons les résultats mis en cache que s'il y a du contenu. Sinon, l'instruction IF continuera uniquement à exécuter le code ordinaire.

La troisième implémentation - qu'en est-il du temps d'expiration?

Jusqu'à présent, nous utilisons SessionStorage, c'est comme LocalStorage, juste que SessionStorage est effacé lorsque vous démarrez un nouvel onglet. Cela signifie que nous tirons parti d'un "moyen naturel" pour éviter le temps de cache trop longtemps. Si nous utilisons localStorage à la place et mettons en cache quelque chose, il restera toujours coincé même si le contenu distant a changé, ce qui est mauvais.

Une meilleure solution consiste à laisser le contrôle de l'utilisateur . (Dans ce cas, l'utilisateur est le développeur Web qui utilise notre fonction CachedFetch). Tout comme Memcached ou Redis Storage côté serveur, vous pouvez définir une durée de vie qui spécifie la durée de la mise en cache.

par exemple, dans Python (en utilisant Flask):

let origin = null;
fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(information => {
    origin = information.origin; // 您的客户端IP
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  console.log('您的来源是 ' + origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Maintenant, ni SessionStorage ni LocalStorage n'ont intégré cette fonctionnalité, nous devons donc l'implémenter manuellement. Nous le ferons en enregistrant toujours l'horodatage du temps stocké et en l'utilisant pour comparer les éventuels coups sûrs de cache.

Mais à quoi cela ressemblera-t-il avant de faire cela? Par exemple:

fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(info => {
    sessionStorage.setItem('information', JSON.stringify(info));
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  let info = JSON.parse(sessionStorage.getItem('information'));
  console.log('您的来源是 ' + info.origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion

La nouvelle chose clé que nous ajouterons est que chaque fois que nous enregistrons les données de réponse, nous enregistrerons également quand quand le stockerons. Mais veuillez noter que maintenant nous pouvons également passer à un stockage plus fiable de LocalStorage au lieu de SessionStorage. Notre code expiré personnalisé garantira que nous n'obtenons pas des coups de cache très périmés dans le storage local persistant. donc c'est notre solution de travail ultime:

fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(issues => {
    console.log('您的来源是 ' + info.origin);
  });
Copier après la connexion
Copier après la connexion
Exemple de codepen

La réalisation du futur - mieux, plus fantaisie, plus cool

Non seulement nous évitons de sureffecter ces API Web, mais la meilleure partie est que LocalStorage est beaucoup plus rapide que les réseaux dépendants. Veuillez vous référer à cet article de blog pour une comparaison de LocalStorage vs XHR:

localforage vs Xhr

. Il mesure d'autres choses, mais conclut essentiellement que le storage local est très rapide et que l'échauffement du cache disque est rare. Alors, comment améliorer davantage nos solutions?

Traitement de la réponse binaire

Notre implémentation ici ne cache pas le contenu non texte (comme les images), mais il n'y a aucune raison de ne pas se cacher. Nous avons besoin de plus de code. En particulier, nous voulons peut-être stocker plus d'informations sur le blob. Chaque réponse est essentiellement un blob. Pour le texte et JSON, ce n'est qu'un éventail de chaînes. Le type et la taille n'ont pas d'importance, car vous pouvez déduire de la chaîne elle-même. Pour le contenu binaire, le BLOB doit être converti en ArrayBuffer.

Pour les gens curieux, pour afficher les extensions d'implémentation qui prennent en charge les images, veuillez vérifier ce codep: [https://www.php.cn/link/946af35555203afdb63e571b873e419f6].

Utiliser la clé de cache de hachage

Une autre amélioration potentielle consiste à échanger l'espace contre la vitesse en hachant chaque URL (nous utilisons comme clés) pour la rendre plus petite. Dans l'exemple ci-dessus, nous n'utilisons que des URL très petites et concises (par exemple httpbin.org/get), mais si vous avez de très longues URL, il y a beaucoup de contenu de chaîne de requête, et il y a beaucoup de ces URL , alors ils s'ajouteront beaucoup.

La solution à ce problème consiste à utiliser cet algorithme intelligent, qui est considéré comme sûr et rapide:

let origin = null;
fetch('https://httpbin.org/get')
  .then(r => r.json())
  .then(information => {
    origin = information.origin; // 您的客户端IP
  });

// 需要延迟以确保fetch已完成
setTimeout(() => {
  console.log('您的来源是 ' + origin);
}, 3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Si vous aimez cela, consultez ce codePen: [https://www.php.cn/link/946af355203afdb63e571b873e419f6]. Si vous vérifiez le stockage dans la console Web, vous verrez une clé similaire à 557027443.

Conclusion

Vous avez maintenant une solution de travail que vous pouvez ajouter à votre application Web, où vous utilisez probablement l'API Web et vous savez que les réponses peuvent être bien mises en cache pour vos utilisateurs.

La dernière chose pourrait être une extension naturelle de ce prototype, c'est-à-dire pour le déplacer au-delà de l'article, dans un projet réel et spécifique avec des tests et des lectures et le publier sur NPM - mais cela doit être dit plus tard!

FAQ sur les demandes ajax extraites (FAQ)

Quelle est l'importance de la mise en cache des demandes Ajax récupérées?

Les demandes AJAX sont essentielles à la mise en cache pour améliorer les performances de votre application Web. Il permet au navigateur de stocker une copie de la réponse du serveur afin qu'il n'ait pas à refaire la même demande. Cela réduit la charge sur le serveur et accélère le temps de chargement de la page Web, offrant ainsi une meilleure expérience utilisateur.

Comment fonctionne l'API Fetch avec Cache?

API Fetch fournit un moyen puissant et flexible de faire des demandes HTTP. Il comprend un mécanisme de mise en cache intégré qui vous permet de spécifier comment les demandes doivent interagir avec le cache. Vous pouvez définir le mode de cache sur "par défaut", "sans magasin", "rechargement", "sans cache", "force-cache" ou "uniquement si-cache", chacun avec différents niveaux de contrôle du cache.

Quels sont les différents modes de cache de l'API Fetch et que signifient-ils?

L'API Fetch fournit plusieurs modes de cache. "par défaut" suit les règles de mise en cache HTTP standard. "Pas de magasin" contourne complètement le cache. "Recharger" ignore toutes les données mises en cache et envoie de nouvelles demandes. "No-Cache" utilise le serveur pour vérifier les données avant d'utiliser la version mise en cache. "Force-Cache" utilise des données mises en cache quelle que soit sa fraîcheur. "uniquement IF-cache" ne l'utilise que lorsque les données de cache sont disponibles, sinon elles échouent.

Comment implémenter le cache dans la demande ajax?

Vous pouvez implémenter le cache dans les demandes AJAX en définissant l'attribut de cache dans les paramètres AJAX. S'il est défini sur true, cela permettra au navigateur de mettre en cache la réponse. Alternativement, vous pouvez utiliser les options de cache de l'API Fetch pour mieux contrôler le comportement du cache.

Comment empêcher le cache dans les demandes AJAX?

Pour empêcher la mise en cache dans les demandes AJAX, vous pouvez définir la propriété Cache dans les paramètres AJAX sur FALSE. Cela obligera le navigateur à ne pas stocker sa réponse dans son cache. Alternativement, vous pouvez utiliser l'option de mise en cache "sans magasin" de l'API Fetch pour contourner entièrement le cache.

Quelle est la différence entre la mise en cache dans AJAX et API Fetch?

Bien que les API AJAX et les API fetch fournissent des mécanismes de mise en cache, l'API Fetch offre une plus grande flexibilité et contrôle. La propriété Cache d'Ajax est une simple valeur booléenne qui permet ou ne permet pas le cache. D'un autre côté, l'option de cache de l'API Fetch vous permet de spécifier comment les demandes doivent interagir avec le cache, vous donnant un contrôle plus granulaire.

Comment la mise en cache affecte-t-elle les performances de mon application Web?

Le cache peut considérablement améliorer les performances des applications Web. En stockant une copie de la réponse du serveur, le navigateur n'a pas à refaire la même demande. Cela réduit la charge sur le serveur et accélère le temps de chargement de la page Web. Cependant, le cache doit être géré correctement pour garantir que vos utilisateurs voient le dernier contenu.

Puis-je contrôler le comportement de cache d'une seule demande AJAX?

Oui, vous pouvez contrôler le comportement de cache d'une seule demande AJAX en définissant l'attribut de cache dans les paramètres AJAX pour chaque demande. Cela vous permet de spécifier si le navigateur doit mettre en cache la réponse.

Comment effacer le cache des demandes AJAX?

Effacer le cache demandé par AJAX peut être effectué en définissant la propriété de cache sur FALSE dans les paramètres AJAX. Cela obligera le navigateur à ne pas stocker sa réponse dans son cache. Alternativement, vous pouvez utiliser l'option de cache "Recharger" de l'API Fetch pour ignorer toutes les données mises en cache et envoyer de nouvelles demandes.

Quelles sont les meilleures pratiques pour la mise en cache des demandes AJAX?

Certaines meilleures pratiques pour la mise en cache des demandes AJAX incluent: Comprendre différents modes de cache et quand les utiliser, gérer correctement le cache pour garantir que les utilisateurs voient le dernier contenu et l'utilisation des options de cache de l'API Fetch pour un meilleur contrôle sur les caches. Lors de la décision d'une stratégie de mise en cache, la nature des données et de l'expérience utilisateur doit également être prise en compte.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal