les erreurs
Parlons d'erreurs.
Il existe deux types d'erreurs:
- erreurs attendues
- erreurs inattendues
- erreurs ponctuelles
Erreurs attendues
Les erreurs attendues sont des états où la mauvaise chose se produit, mais vous savez que cela peut arriver, vous devez donc y faire face.
Ce sont des choses comme l'entrée d'utilisateur ou les demandes du serveur. Vous savez que l'utilisateur peut faire une erreur ou que le serveur est en panne, vous écrivez donc du code de vérification pour vous assurer que le programme demande à nouveau une entrée, ou affiche un message, ou tout autre comportement approprié.
Ceux-ci sont récupérables lorsqu'ils sont manipulés. S'ils ne sont pas manipulés, ils deviennent des erreurs inattendues.
Erreurs inattendues
Les erreurs inattendues (bogues) sont des états où la mauvaise chose se produit parce que le code est incorrect. Vous savez qu'ils finiront par se produire, mais il n'y a aucun moyen de savoir où ou comment les traiter car, par définition, ils sont inattendus.
Ce sont des choses comme la syntaxe et les erreurs logiques. Vous pouvez avoir une faute de frappe dans votre code, vous avez peut-être appelé une fonction avec les mauvais paramètres. Ceux-ci ne sont généralement pas récupérables.
try..catch
Parlons de try..catch
.
En JavaScript, throw
n'est pas couramment utilisé. Si vous regardez des exemples dans le code, ils seront peu nombreux et généralement structurés dans le sens de
function example(param) {
if (!Array.isArray(param) {
throw new TypeError('"param" should be an array!');
}
...
}
À cause de ce, try..catch
blocs ne sont pas tous communs non plus pour le flux de contrôle. Il est généralement assez facile d'ajouter quelques vérifications avant d'appeler des méthodes pour éviter les erreurs attendues.
Les environnements JavaScript sont également assez indulgents, donc les erreurs inattendues sont souvent laissées non détectées également.
try..catch
ne doit pas être rare. Il existe de bons cas d'utilisation, qui sont plus courants dans des langages tels que Java et C #. Java et C # ont l'avantage de tapercatch
constructions , de sorte que vous pouvez faire la différence entre les erreurs attendues et inattendues:
C # :
try
{
var example = DoSomething();
}
catch (ExpectedException e)
{
DoSomethingElse(e);
}
Cet exemple permet à d'autres exceptions inattendues de remonter et d'être gérées ailleurs (par exemple en étant connecté et en fermant le programme).
En JavaScript, cette construction peut être répliquée via:
try {
let example = doSomething();
} catch (e) {
if (e instanceOf ExpectedError) {
DoSomethingElse(e);
} else {
throw e;
}
}
Pas aussi élégant, ce qui explique pourquoi c'est rare.
Les fonctions
Parlons des fonctions.
Si vous utilisez le principe de responsabilité unique , chaque classe et chaque fonction doivent avoir un objectif unique.
Par exemple, authenticate()
peut authentifier un utilisateur.
Cela pourrait être écrit comme suit:
const user = authenticate();
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
Alternativement, il peut être écrit comme suit:
try {
const user = authenticate();
// keep doing stuff
} catch (e) {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
}
Les deux sont acceptables.
Promesses
Parlons de promesses.
Les promesses sont une forme asynchrone de try..catch
. Appelez new Promise
ou Promise.resolve
commencez votre try
code. Appelant throw
ou Promise.reject
vous envoie le catch
code.
Promise.resolve(value) // try
.then(doSomething) // try
.then(doSomethingElse) // try
.catch(handleError) // catch
Si vous avez une fonction asynchrone pour authentifier un utilisateur, vous pouvez l'écrire comme:
authenticate()
.then((user) => {
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
});
Alternativement, il peut être écrit comme suit:
authenticate()
.then((user) => {
// keep doing stuff
})
.catch((e) => {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
});
Les deux sont acceptables.
Imbrication
Parlons de l'imbrication.
try..catch
peut être imbriqué. Votre authenticate()
méthode peut avoir en interne un try..catch
bloc tel que:
try {
const credentials = requestCredentialsFromUser();
const user = getUserFromServer(credentials);
} catch (e) {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
}
De même, les promesses peuvent être imbriquées. Votre authenticate()
méthode asynchrone peut utiliser en interne des promesses:
requestCredentialsFromUser()
.then(getUserFromServer)
.catch((e) => {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
});
Alors, quelle est la réponse?
Ok, je pense qu'il est temps pour moi de répondre à la question:
Un échec de l'authentification est-il considéré comme une chose pour laquelle vous rejetteriez une promesse?
La réponse la plus simple que je puisse donner est que vous devriez rejeter une promesse partout où vous voudriez autrement throw
une exception s'il s'agissait d'un code synchrone.
Si votre flux de contrôle est plus simple en ayant quelques if
vérifications dans vos then
relevés, il n'est pas nécessaire de rejeter une promesse.
Si votre flux de contrôle est plus simple en rejetant une promesse puis en vérifiant les types d'erreurs dans votre code de gestion des erreurs, faites-le à la place.
reject
et ne retournez pas faux, mais si vous attendez la valeur d'êtreBool
, alors vous étiez avec succès et vous devez résoudre avec le Bool quelle que soit la valeur. Les promesses sont en quelque sorte des procurations pour les valeurs - elles stockent la valeur renvoyée, donc seulement si la valeur n'a pas pu être obtenuereject
. Sinon, vous devriezresolve
.