Fermer

avril 12, 2018

Comment utiliser les proxies –


En termes informatiques, les proxies s'interposent entre vous et les éléments avec lesquels vous communiquez. Le terme est le plus souvent appliqué à un serveur proxy – un périphérique entre le navigateur Web (Chrome, Firefox, Safari, Edge, etc.) et le serveur Web (Apache, Nginx, IIS, etc.) où se trouve une page. Le serveur proxy peut modifier les demandes et les réponses. Par exemple, il peut augmenter l'efficacité en mettant en cache les ressources régulièrement consultées et en les diffusant auprès de plusieurs utilisateurs.

Les proxys ES6 se trouvent entre votre code et un objet. Un proxy vous permet d'effectuer des opérations de métaprogrammation telles que l'interception d'un appel pour inspecter ou modifier la propriété d'un objet.

La terminologie suivante est utilisée pour les proxys ES6:

target
L'objet original le proxy va virtualiser. Cela pourrait être un objet JavaScript tel que la bibliothèque jQuery ou des objets natifs tels que des tableaux ou même d'autres proxies

handler
Un objet qui implémente le comportement du proxy en utilisant …

traps
] Fonctions définies dans le gestionnaire qui permettent d'accéder à la cible lorsque des propriétés ou des méthodes spécifiques sont appelées

Il est préférable de l'expliquer par un exemple simple. Nous allons créer un objet cible nommé target qui a trois propriétés:

 const target = {
  a: 1,
  b: 2,
  c: 3
}

Nous allons maintenant créer un objet handler qui intercepte toutes les opérations get . Cela retourne la propriété de la cible quand elle est disponible ou 42 sinon:

 const handler = {
  get: function (cible, nom) {
    revenir (
      nom dans la cible? Cible [name]: 42
    )
  }
}

Nous créons maintenant un nouveau proxy en passant les objets target et handler. Notre code peut interagir avec le proxy plutôt que d'accéder directement à l'objet cible :

 const proxy = new Proxy (target, handler);

console.log (proxy.a); // 1
console.log (proxy.b); // 2
console.log (proxy.c); // 3
console.log (proxy.meaningOfLife); // 42

Développons le gestionnaire proxy de manière à ce qu'il ne permette que les propriétés à un caractère de a à z à définir:

 const handler = {
  get: function (cible, nom) {
    return (nom dans la cible? target [name]: 42);
  },

  set: function (cible, prop, valeur) {
    if (prop.length == 1 && prop> = 'a' && prop <= 'z') {
      cible [prop] = valeur;
      retourner vrai;
    }
    autre {
      throw new ReferenceError (prop + 'ne peut pas être défini');
      return false;
    }
  }
}

const proxy = new Proxy (cible, gestionnaire);

proxy.a = 10;
proxy.b = 20;
proxy.ABC = 30;
// Exception: ReferenceError: ABC ne peut pas être défini

Types de pièges proxy

Nous avons vu le obtenir et définir en action, qui sont susceptibles d'être les pièges les plus utiles. Cependant, il existe plusieurs autres types de pièges que vous pouvez utiliser pour compléter le code du gestionnaire de proxy:

  • construct (target, argList)
    Intercepte la création d'un nouvel objet avec l'opérateur . get (target, property)
    Traps Object.get () et doit renvoyer la valeur de la propriété
  • set (target, property, value)
    Traps Object.set ( ) et doit définir la valeur de la propriété. Retour true en cas de succès. En mode strict, renvoyer false lancera une exception TypeError
  • deleteProperty (target, property)
    Intercepte une opération delete sur la propriété d'un objet. Doit retourner soit vrai soit faux .
  • apply (cible, thisArg, argList)
    Traps appels de fonction d'objet.
  • has (target, property)
    Traps dans opérateurs et doit renvoyer soit true soit false .
  • ownKeys (cible)
    Traps Object.getOwnPropertyNames () et doit retourner un objet énumérable
  • getPrototypeOf (target)
    Traps Object.getPrototypeOf () et doit renvoyer l'objet du prototype ou null
  • setPrototypeOf (target, prototype)
    ] Interruptions Object.setPrototypeOf () pour définir l'objet prototype.
  • isExtensible (target)
    Traps Object.isExtensible () qui détermine si un objet peut avoir de nouvelles propriétés ajoutées. Doit retourner true ou false .
  • preventExtensions (target)
    Traps Object.preventExtensions () qui empêche l'ajout de nouvelles propriétés à un objet. Doit retourner soit true soit false .
  • getOwnPropertyDescriptor (cible, propriété)
    Traps Object.getOwnPropertyDescriptor () qui renvoie undefined ou une propriété objet descripteur avec des attributs pour valeur inscriptible get ensemble configurable et énumérable
  • defineProperty (cible, propriété, descripteur)
    Traps Object.defineProperty () qui définit ou modifie une propriété d'objet. Doit retourner true si la propriété target a été définie avec succès ou false sinon

Proxy Example 1: Profiling

Les proxies vous permettent de créer des wrappers génériques pour n'importe quel objet sans avoir pour modifier le code dans les objets cibles eux-mêmes.

Dans cet exemple, nous allons créer un proxy de profilage qui compte le nombre de fois où une propriété est accédée. Tout d'abord, nous avons besoin d'une fonction d'usine makeProfiler qui renvoie l'objet Proxy et conserve l'état de comptage:

 // créer un proxy de profilage
function makeProfiler (cible) {

  const
    compte = {},
    gestionnaire = {

      get: function (cible, nom) {
        if (nom dans la cible) {
          compte [name] = (compte [name] || 0) + 1;
          cible de retour [name];
        }
      }
    }

  revenir {
    proxy: nouveau proxy (cible, gestionnaire),
    compter: compter
  }
}

Nous pouvons maintenant appliquer ce wrapper de proxy à n'importe quel objet ou un autre proxy. Par exemple:

 const myObject = {
  h: 'Bonjour',
  w: 'Monde'
}

// crée un proxy myObject
const pObj = makeProfiler (monObjet);

// accéder aux propriétés
console.log (pObj.proxy.h); // Bonjour
console.log (pObj.proxy.h); // Bonjour
console.log (pObj.proxy.w); // Monde
console.log (pObj.count.h); // 2
console.log (pObj.count.w); // 1

Bien que ce soit un exemple trivial, imaginez l'effort requis si vous deviez effectuer des comptages d'accès aux propriétés dans plusieurs objets différents sans utiliser de proxy

Exemple de proxy 2: Liaison de données bidirectionnelle

Il est généralement utilisé dans les bibliothèques MVC JavaScript pour mettre à jour un objet interne lorsque le DOM change et vice versa.

Supposons que nous ayons un champ de saisie avec un ID de inputname :

  

Nous avons aussi un objet JavaScript nommé myUser avec une propriété id qui fait référence à cette entrée:

 // état interne pour le champ #inputname
const myUser = {
  id: 'nom d'entrée',
  prénom: ''
}

Notre premier objectif est de mettre à jour myUser.name lorsqu'un utilisateur modifie la valeur d'entrée. Cela peut être réalisé avec un gestionnaire d'événement onchange sur le champ:

 inputChange (myUser);

// lie l'entrée à l'objet
function inputChange (monObjet) {
  if (! myObject ||! myObject.id) renvoie;

  const input = document.getElementById (monObjet.id);
  input.addEventListener ('onchange', fonction (e) {
    myObject.name = input.value;
  });
}

Notre prochain objectif est de mettre à jour le champ de saisie lorsque nous modifions myUser.name dans le code JavaScript. Ce n'est pas aussi simple, mais les proxies offrent une solution:

 // gestionnaire de proxy
const inputHandler = {
  set: function (target, prop, nouvelleValeur) {
    if (prop == 'nom' && target.id) {
      // mise à jour de la propriété
      target [prop] = nouvelle valeur;

      // met à jour la valeur du champ d'entrée
      document.getElementById (target.id) .value = nouvelleValeur;
      retourner vrai;
    }
    sinon, retournez faux;
  }
}

// crée un proxy
const myUserProxy = nouveau proxy (myUser, inputHandler);

// définir un nouveau nom
myUserProxy.name = 'Craig';
console.log (myUserProxy.name); // Craig
console.log (document.getElementById ('nom d'entrée'). value); // Craig

Cela peut ne pas être l'option de liaison de données la plus efficace, mais les proxies vous permettent de modifier le comportement de nombreux objets existants sans changer leur code

Hemanth.HM's article Negative Array Index en JavaScript suggère d'utiliser des proxies pour implémenter des index de tableaux négatifs. Par exemple, arr [-1] renvoie le dernier élément, arr [-2] renvoie l'avant-dernier élément, et ainsi de suite

L'article de Nicholas C. Zakas propriétés de sécurité avec des proxies ECMAScript 6 illustre comment les proxies peuvent être utilisés pour implémenter la sécurité de type en validant de nouvelles valeurs. Dans l'exemple ci-dessus, nous pouvions vérifier myUserProxy.name était toujours défini sur une chaîne et renvoyer une erreur sinon

Proxy Support

Le pouvoir des proxies n'est peut-être pas évident, mais ils offrent puissantes opportunités de méta-programmation. Brendan Eich, le créateur de JavaScript, pense Proxies are Awesome !

Actuellement, le support de proxy est implémenté dans Node et tous les navigateurs actuels, à l'exception d'Internet Explorer 11. Cependant, s'il vous plaît noter que tous les navigateurs supportent tous les pièges. Vous pouvez avoir une meilleure idée de ce qui est supporté en consultant cette table de compatibilité du navigateur sur la page MDN Proxy

Malheureusement, il n'est pas possible de polyfill ou transpile le code proxy ES6 en utilisant des outils tels que parce que les proxies sont puissants et n'ont pas d'équivalent ES5.






Source link