Presque tous ceux qui utilisent JavaScript quotidiennement savent que try-catch peut être pénible à gérer, surtout lorsque vous avez plus d'une erreur à gérer.
La plupart des solutions proposées tentent de copier l'approche de Golang - qui gère tout comme des valeurs de retour. C'est, entre autres choses, une fonctionnalité intéressante de Go, mais JS est un langage complètement différent (duh) et je pense que nous pouvons faire mieux qu'un copier-coller de Go.
En Go, lorsque nous voulons gérer une erreur, nous la renvoyons depuis l'appel de fonction soit comme deuxième valeur dans un tuple, soit comme valeur de retour de l'appel de fonction. Voici le modèle :
result, error := DoSomething() if error != nil { // handle error }
Cette approche permet de gérer les erreurs explicitement à l'aide d'un flux de contrôle standard.
Pour appliquer ce modèle en javascript, la solution la plus courante consiste à renvoyer les résultats sous forme de tableau :
const handler = async (promise) => { try { const result = await promise() return [result, null]; } catch(error) { return [null, error]; } } const [response, error] = await handle(fetch('http://go.gl')) if (error !== null) { // handle error }
Comme vous pouvez le voir, il s'agit d'un copier-coller presque direct du modèle de Go.
Ce modèle fonctionne très bien, mais en javascript, nous pouvons faire mieux que cela. L'idée principale de ce modèle est de renvoyer l'erreur sous forme de valeur, adaptons-la donc avec un meilleur SoC.
Au lieu de renvoyer null ou Error, nous pouvons décorer le résultat avec une interface cohérente. Cela améliorerait notre SoC et nous donnerait une valeur de retour fortement typée :
interface Status { Ok(): boolean; Fail(): boolean; Of(cls: any): boolean; }
Le statut de l'interface ne doit pas nécessairement être une erreur, mais nous pouvons vérifier son type en utilisant status.Of(Error). Nous pouvons toujours renvoyer un objet qui satisfait au statut. L'exemple d'utilisation serait :
const [response, error] = await handle(res.json()) if (error.Of(SyntaxError)) { // handle error console.log("not a json") return }
Maintenant, en JavaScript, notre résultat ne doit pas toujours être un tuple. Nous pouvons en fait créer notre propre classe qui se comporte comme un tuple lorsque cela est nécessaire :
interface IResult<T> { 0: T; 1: Status; value: T; status: Status; Of(cls: any): boolean; Ok(): boolean; Fail(): boolean; }
Exemple d'utilisation :
const result = await handle(res.value.json()) if (result.Of(SyntaxError)) { // handle error console.log("not a json") return }
En suivant cette approche, j'ai créé une fonction prête à l'emploi - Grip.
Grip est fortement typé et peut agrémenter aussi bien des fonctions que des promesses.
J'utilise git pour héberger de tels packages, donc pour installer, utilisez github :
bun add github:nesterow/grip # or pnpm
La fonction grip accepte une fonction ou une promesse et renvoie un résultat avec une valeur de retour et un statut.
Le résultat peut être traité sous forme d'objet ou de tuple.
import { grip } from '@nesterow/grip';
Le résultat peut être géré comme un objet : {value, status, Ok(), Fail(), Of(type)}
const res = await grip( fetch('https://api.example.com') ); if (res.Fail()) { handleErrorProperly(); return; } const json = await grip( res.value.json() ); if (json.Of(SyntaxError)) { handleJsonParseError(); return; }
Le résultat peut également être reçu sous forme de tuple si vous souhaitez gérer les erreurs en style Go'ish :
const [res, fetchStatus] = await grip( fetch('https://api.example.com') ); if (fetchStatus.Fail()) { handleErrorProperly(); return; } const [json, parseStatus] = await grip( res.json() ); if (parseStatus.Of(SyntaxError)) { handleJsonParseError(); return; }
Si vous aimez cette approche de la gestion des erreurs, consultez le référentiel. La source est d'environ 50LOC, sans types, et 100 avec types.
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!