12
votes

Une API ASYNC devrait-elle jamais jeter de manière synchrone?

J'écris une fonction JavaScript qui fait une demande HTTP et renvoie une promesse pour le résultat (mais cette question s'applique également à une implémentation basée sur le rappel).

Si je sais immédiatement que les arguments fournis pour la fonction sont invalides, la fonction lancer de manière synchrone ou doit-elle renvoyer une promesse rejetée (ou, si vous préférez, appelez le rappel avec une erreur d'erreur < p> Quelle est l'importance de ce que la fonction async doit toujours se comporter de manière asynchrable, en particulier pour les conditions d'erreur? Est-ce correct à lancer si vous savez que le programme n'est pas dans un état approprié pour l'opération ASYNC pour continuer?

par exemple: xxx


5 Réponses :


7
votes

En fin de compte, la décision de lancer de manière synchrone ou non est à vous, et vous trouverez probablement des personnes qui soutiennent de chaque côté. L'important est de documenter le comportement et de maintenir la cohérence dans le comportement.

Mon avis sur la question est que votre deuxième option - transmettre l'erreur dans le rappel - semble plus élégante. Sinon vous vous retrouvez avec du code qui ressemble à ceci: xxx

Le flux de contrôle ici est légèrement déroutant.

Il semble que ce soit mieux d'avoir Un seul si / else si / else structure dans le rappel et renverser le Essayez / attrapez


0 commentaires

3
votes

Quelle est l'importance de ce que la fonction async doit toujours se comporter de manière asynchratante, en particulier pour les conditions d'erreur?

très important .

est-ce correct de lancer si vous savez que le programme n'est pas dans un état approprié pour l'opération ASYNC pour continuer?

Oui, je pense personnellement que c'est OK quand c'est une erreur très différente de tous les a fabriqués de manière asynchrone et doit être traitée séparément de toute façon.

Si certains ID utilisateur sont connus pour être invalides car ils ne sont pas numériques, et certains sont rejetés sur le serveur (par exemple parce qu'ils sont déjà pris), vous devez constamment faire un rappel (async!) pour les deux cas. Si les erreurs ASYNC ne proviennent que des problèmes de réseau, etc., vous pourriez les signaler différemment.

Vous pouvez toujours lancer quand une erreur " inattendue " est. Si vous exigez des userids valides, vous pourriez lancer sur ceux invalides. Si vous souhaitez anticiper des personnes non valides et que l'appelant les gère, vous devez utiliser une route d'erreur «unifiée» qui serait la promesse de rappel / rejetée pour une fonction asynchrone.

et pour répéter @Timothy: vous devez toujours documenter le comportement et maintenir la cohérence dans le comportement.


0 commentaires

1
votes

Les API de rappel Idéalement, ne devraient pas lancer mais ils jetent parce qu'il est très difficile d'éviter depuis que vous devez essayer de prendre littéralement partout. N'oubliez pas que l'erreur de lancer explicitement par lancer code> n'est pas requise pour une fonction à lancer. Une autre chose qui ajoute à ceci est que le rappel de l'utilisateur peut facilement lancer également, par exemple appelant json.parse code> sans essayer de prendre.

C'est ce que le code ressemblerait à ce que le code se comporte selon ces Idéaux: P>

readFile("file.json").then(JSON.parse).then(function(val) {
    console.log(val.success);
})
.catch(SyntaxError, function(e) {
    console.error("invalid json in file");
})
.catch(function(e){
    console.error("unable to read file")
})


1 commentaires

Si ce Listerfile lance une exception, il ne sera pas attrapé par les fonctions de capture définies là-bas. Mais si le disque de lecture retourne une promesse, alors ça marche



1
votes

C'est en grande partie une question d'opinion. Tout ce que vous faites, faites-le de manière cohérente et de le documenter clairement.

Une information objective que je peux vous donner est que cela faisait l'objet de nombreuses discussions dans la conception des fonctions code> async code> de JavaScript, qui Comme vous le savez peut-être implicitement retourner des promesses pour leur travail. Vous pouvez également savoir que la partie d'un async code> fonction avant le premier attendre code> ou retour code> est synchrone fort>; Il ne devient aussi asynchrone qu'au point IT attendre code> s ou retours. p>

TC39 a décidé à la fin que même les erreurs lancées dans la partie synchrone d'un async code> La fonction devrait rejeter sa promesse plutôt que de soulever une erreur synchrone. Par exemple: p>

p>

async function someAsyncStuff() {
    return 21;
}

function example() {
    console.log("synchronous part of function");
    throw new Error("failed");
    return someAsyncStuff().then(x => x * 2);
}
try {
    console.log("before call");
    example().catch(e => { console.log("asynchronous:", e.message); });
    console.log("after call");
} catch (e) {
    console.log("synchronous:", e.message);
}


0 commentaires

0
votes

Idéalement, vous auriez une architecture multicouche comme des contrôleurs, des services, etc. Si vous faites des validations dans des services, jetez immédiatement et avez un bloc de capture dans votre contrôleur pour saisir le format d'erreur et envoyer un code d'erreur HTTP approprié. De cette façon, vous pouvez centraliser toute la logique de manutention de mauvaise demande. Si vous gérez chaque cas, vous finirez par écrire plus de code. Mais c'est comme ça que je le ferais. Dépend de votre cas d'utilisation


0 commentaires