La métaprogrammation réalise un chargement paresseux élégant

Si vous voulez regarder directement le code EcmaScript qui utilise des intercepteurs getter pour implémenter le chargement différé des ressources, et que vous ne voulez pas m'entendre parler de beaucoup de théories, vous pouvez commencer directement à partir du quatrième titre.


  • Généralisation des termes professionnels

L'industrie informatique s'est développée pendant tant d'années et d'innombrables termes professionnels sont apparus. Certains termes anciens sont dépassés et oubliés par les gens. Cependant, certains termes anciens ne sont pas seulement obsolètes, mais sont également passés de leurs propres concepts étroits à des concepts philosophiques généraux.

Par exemple, «duplex» lui-même est un terme désignant le sens de transmission des lignes de données dans une liaison physique, et il est maintenant utilisé pour décrire le mode de transmission entre tous les pairs; par exemple, «idempotence» était à l'origine un terme mathématique, mais il est maintenant utilisé Pour décrire le comportement de l'interface serveur. Il existe de nombreux exemples de cela, pensez à quelques-uns: ce que «codage», «E / S», «découplage» et «sérialisation». . .

Le nom dont je vais parler aujourd'hui est «chargement paresseux». Lazy Load / Load On Demand est un moyen pour les navigateurs de charger des images à la demande à l'ère du web1.0. Étant donné que la vitesse d'Internet était très lente à l'époque, afin d'économiser de la bande passante, seuls les éléments d'image qui entraient dans la vue d'écran étaient temporairement téléchargés et combinés afficher. Mais lorsque vous faites défiler à nouveau l'image, vous n'avez pas besoin de la charger à nouveau.

Bien que les images de la page Web actuelle soient également chargées de cette manière, le terme «chargement paresseux» a été transmis parce que de nombreux endroits ont incarné la philosophie du chargement paresseux. Par exemple, le chargement du module de routage back-end http nécessite certaines ressources, vous pouvez donc attendre que l'utilisateur en premier Chargez cette interface de routage une fois que vous l'avez visitée, et vous n'avez pas besoin de la charger la deuxième fois que vous la visitez.


  • Les conditions nécessaires et suffisantes pour le chargement paresseux

Nous spécifions donc une proposition pour le chargement différé, y compris dans quelles circonstances le chargement différé devrait être utilisé et comment le chargement différé devrait être effectué:

  1. Le chargement d'une ressource prend plus de temps ou d'espace

  2. Mais les ressources obtenues à chaque fois sont exactement les mêmes (les ressources ne changeront pas dynamiquement)

  3. Cette ressource peut devoir être lue 0 fois, 1 fois ou plusieurs fois.

  4. Chargé à la première lecture, puis mis en cache

  5. Lire le cache pour la deuxième fois et au-delà

Si l'une des conditions nécessaires et suffisantes ci-dessus n'est pas respectée, il n'est pas nécessaire d'utiliser le chargement paresseux ou le chargement paresseux est mal utilisé! Examinez de plus près la première condition, en fait, le chargement paresseux peut également être appelé d'autres noms, tels que le calcul paresseux, la demande paresseuse, le stockage paresseux. . . Quoi qu'il en soit, cela signifie la même chose: effectuer une tâche chronophage ou encombrante dans une attitude paresseuse (chargement paresseux).


  • Utilisez des getters pour charger paresseusement avec élégance

Pourquoi l'appeler élégant chargement paresseux? Comme il existe de nombreuses façons d'implémenter le chargement différé, beaucoup d'entre elles utilisent une variable externe pour indiquer si la ressource a été chargée. Vous devez d'abord juger à chaque fois que vous la chargez. Mais comme la variable d'état et la fonction de chargement sont un-à-un, il sera préférable de les combiner, par exemple en suspendant la variable d'état à la fonction de chargement.

Mais une meilleure façon est d'utiliser l'intercepteur getter d'EcmaScript pour effectuer une "métaprogrammation". La fonction du getter lui-même est de calculer temporairement une certaine valeur pendant get. Prenons l'exemple suivant:

const foo = {
    x: 3,
    y: 4,
    get xy() {
        return this.x * this.y;
    }
};


foo.xy;  // 12

Parmi eux, x et y sont des variables, et xy représente le produit de x et y. Chaque fois que x et y changent, xy n'a pas besoin de changer, et seulement quand on accède à xy, le produit quantitatif est temporairement calculé. Est-ce déjà un peu "paresseux"? Cependant, comme x et y ne sont pas des constantes et ne remplissent pas les conditions nécessaires et suffisantes pour le chargement paresseux, la situation réelle est souvent lorsque le getter a une grande quantité de calcul, comme le craquage par force brute d'un mot de passe faible fixe.


  • Exemple

Si nous voulons calculer la valeur réelle de la barre lorsque nous lisons foo.bar pour la première fois, puis lisons cette valeur calculée, mais à chaque fois que nous lirons foo.bar, nous ne sentirons pas la différence dans le code, c'est-à-dire " élégant".

S'il y a une page avec 100 000 éléments dom sur la page, il est trop difficile de trouver l'élément <foo id = "bar"> </foo> via le sélecteur d'id. Le moteur espère le trouver si ce n'est pas possible. Trouvez-le juste une fois. Nous pouvons faire de foo un getter. Lorsque nous trouvons <foo> pour la première fois, nous supprimons ce getter et le remplaçons par un attribut foo ordinaire du même nom. L'attribut foo contient le <foo> nouvellement mis en cache. De cette façon, pour la première fois et Toutes les visites ultérieures de foo recevront les mêmes éléments. À l'exception du premier délai, aucune autre différence n'est ressentie. Le code est très simple:

{
    get foo() {
        delete this.foo;
        return this.foo = document.getElementById('bar');
    }
}

La bibliothèque XPCOMUtils.jsm de Firefox a en fait une méthode prête à l'emploi appelée defineLazyGetter: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/XPCOMUtils.jsm#defineLazyGetter ()

(Terminer)


Je suppose que tu aimes

Origine blog.csdn.net/github_38885296/article/details/103917802
conseillé
Classement