Maison  >  Article  >  interface Web  >  Affectation sécurisée

Affectation sécurisée

WBOY
WBOYoriginal
2024-09-10 14:30:15364parcourir

Safe Assignment

Il y a eu beaucoup de buzz aujourd'hui à propos de la nouvelle proposition d'opérateur d'affectation sécurisé (?=) en JavaScript. J'aime la façon dont JavaScript s'est amélioré au fil du temps, mais c'est aussi un problème que j'ai rencontré dans quelques cas récemment. Je devrais concocter un exemple rapide d’implémentation en tant que fonction, n’est-ce pas ?

Au cas où vous n'auriez pas lu la proposition, voici ce qu'elle propose :

const [error, value] ?= maybeThrows();

Le nouvel opérateur ?= équivaudrait à appeler le côté droit de l'affectation dans un bloc try/catch, renvoyant un tableau. La première valeur du tableau renvoyé serait une erreur si quelque chose était lancé à l'intérieur de l'affectation, et la deuxième valeur serait le résultat de l'affectation si rien n'était lancé.

Un désagrément courant d'essai/capture

Je tombe fréquemment sur du code qui semble assez laid autour des blocs d'affectation et d'essai/catch. Des choses comme ça :

let errorMsg;

try {
  maybeThrow();
} catch (e) {
  errorMsg = "An error message";
}

Pour accéder à errorMsg en dehors du bloc try/catch en utilisant const ou laissez-vous devoir le définir en dehors du bloc.

Une implémentation non asynchrone

Le cas le plus simple ici est la gestion des fonctions non asynchrones. J'ai pu concocter
quelques cas de test et une fonction appelée tryCatch en un rien de temps :

function tryCatch(fn, ...args) {
  try {
    return [undefined, fn.apply(null, args)]
  } catch (e) {
    return [e, undefined];
  }
}

function throws() {
  throw new Error("It threw");
}

// returns a sum
// prints [ undefined, 2 ]
console.log(tryCatch(Math.sqrt, 4));

// returns an error
// prints [ Error: 'It threw', undefined ]
console.log(tryCatch(throws));

tryCatch appelle la fonction avec les arguments donnés enveloppés dans un bloc try/catch. Il renvoie de manière appropriée [non défini, résultat] si rien n'est lancé à l'intérieur de la fonction, et [erreur, non défini] si quelque chose est lancé.

Notez que vous pouvez également utiliser une fonction anonyme avec tryCatch si vous n'avez pas déjà de fonction prête à appeler.

console.log(tryCatch(() => {
  throw new Error("It threw");
}));

Gestion des fonctions asynchrones

Les fonctions asynchrones deviennent un peu plus délicates. Une idée que j'ai eu au départ était d'écrire
une version complètement asynchrone, peut-être appelée asyncTryCatch, mais où est le défi là-dedans. C'est une exploration complètement inutile ! Voici une implémentation de tryCatch qui fonctionne avec les fonctions asynchrones et non asynchrones :

function tryCatch(fn, ...args) {
  try {
    const result = fn.apply(null, args);

    if (result.then) {
      return new Promise(resolve => {
          result
            .then(v => resolve([undefined, v]))
            .catch(e => resolve([e, undefined]))  
      }); 
    }

    return [undefined, result];
  } catch (e) {
    return [e, undefined];
  }
}

function throws() {
  throw new Error("It threw");
}

async function asyncSum(first, second) {
  return first + second;
}

async function asyncThrows() {
  throw new Error("It throws async");
}

// returns a sum
// prints [ undefined, 2 ]
console.log(tryCatch(Math.sqrt, 4));

// returns an error
// prints [ Error: 'It threw', undefined ]
console.log(tryCatch(throws));

// returns a promise resolving to value
// prints [ undefined, 3 ]
console.log(await tryCatch(asyncSum, 1, 2));

// returns a promise resolving to error
// prints [ Error: 'It throws async', undefined ]
console.log(await tryCatch(asyncThrows));

Cela ressemble beaucoup à la version originale, mais avec du code basé sur Promise
ajouté pour faire bonne mesure. Avec cette implémentation, vous pouvez appeler tryCatch lors de l'appel d'une fonction non asynchrone, puis appeler wait tryCatch lors de l'appel d'une fonction asynchrone.

Regardons le bit Promesse :

if (result.then) {
  return new Promise(resolve => {
      result
        .then(v => resolve([undefined, v]))
        .catch(e => resolve([e, undefined]))    
  }); 
}

if (result.then) vérifie si la fonction donnée (appelée avec apply) a renvoyé une promesse. Si c’est le cas, nous devons rendre une promesse nous-mêmes.

L'appel de result.then(v => solve([undefined, v])) entraîne la résolution de la promesse à la valeur renvoyée par la fonction donnée, si rien ne se produit.

.catch(e => solve([e, undefined])) est un peu plus délicat. J'ai écrit à l'origine
comme .catch(e => rejet([e, undefined])), mais cela provoque une erreur non détectée
tomber de tryCatch. Nous devons résoudre ici car nous renvoyons un
tableau, ne génère pas d'erreur.

Et enfin

J'ai assez régulièrement des cas où je dois essayer/attraper mais j'ai l'impression que
le bloc try/catch explicite prend une tonne d'espace et est ennuyeux pour les affectations de portée. Je ne sais pas si je vais l'utiliser ou non, mais c'était une petite exploration amusante.

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:
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