Calculer
calc est une fonction asynchrone que nous voulons effectuer une analyse (analyse des performances). Par convention, son dernier paramètre est un callback . Nous utilisons calc comme ceci:
calc (arg, (err, res) => console.log (err || res))
Peut-être que le moyen le plus simple d'analyser les performances d'une fonction comme calc est d'ajouter une logique de synchronisation à l'endroit où nous devons analyser:
const t0 = date.now () calc (arg, (err, res) => {const t1 = date.now () console.log (`log: heure: $ {t1 = t0}`) console.log (err || res)}) Cependant, ce n'est pas une solution réutilisable. Chaque fois que nous voulons chronométrer une fonction, nous devons introduire un T0 dans la portée extérieure et modifier callback pour mesurer et enregistrer l'heure.
La façon idéale pour moi est de pouvoir le chronométrer simplement en emballage une fonction asynchrone:
TimeIt (calc) (arg, (err, res) => console.log (err || res))
timeIt doit être en mesure d'effectuer une analyse et d'enregistrer le temps d'exécution pour chaque fonction asynchrone bien.
Notez que timeIt(calc) a la même signature de fonction que la fonction CALC d'origine, c'est-à-dire qu'ils acceptent les mêmes paramètres et renvoient la même valeur, il ajoute simplement une fonctionnalité au Cale (une fonctionnalité qui peut être enregistrée).
Calc et Timeit (calc) peuvent être remplacés par l'autre à tout moment.
timeIt lui-même est une fonction d'ordre supérieur car il accepte une fonction et renvoie une fonction. Dans notre exemple, il accepte une fonction asynchrone calc et renvoie une fonction avec les mêmes paramètres et la valeur de retour que Calc.
Ce qui suit montre comment nous implémentons la fonction TimeIt:
const timeIt = r.curry ((rapport, f) => (... args) => {const t0 = date.now () const nargs = r.init (args) const callback = r.last (args) nargs.push ((... args) => {const t1 = date.now () callback (args) report (t1 - t0, ... args)}) f (... nargs)}) const timeit1 = timeit ((t, err, res) => console.log (`log: $ {err || res} produit après: $ {t}`)) const calc = (x, y, z, rappel) => settimeout (() => rappel (null, x * y / z), 1000) calc console.log (err || res)) timeIt1 (calc) (18, 7, 3, (err, res) => console.log (err || res)) Cette implémentation timeIt accepte deux paramètres:
Rapport: Une fonction est utilisée pour générer des résultats d'analyse
F: fonction asynchrone que nous voulons faire l'analyse
timeIt1 est une fonction pratique et pratique, il utilise simplement console.log pour enregistrer les résultats de mesure du temps. Nous le définissons en transmettant report à la fonction timeIt la plus générale.
Nous avons atteint l'objectif, et maintenant nous pouvons simplement envelopper la fonction asynchrone dans timeIt1 et le temps il est chronométré:
TimeIt1 (calc) (18, 7, 3, (err, res) => console.log (err || res))
La fonction General timeIt reçoit une fonction de rappel report et une fonction asynchrone et renvoie une nouvelle fonction asynchrone. Cette fonction asynchrone a les mêmes paramètres et la même valeur de retour que la fonction d'origine. Nous pouvons utiliser ceci:
TimeIt ((Time, ... Result) => // Rapport Rappel: log le temps, asyncfunc) (paramètres…, (... result) => // Résultat de la fonction async)
Plongeons maintenant dans la mise en œuvre de timeIt . Nous pouvons simplement générer une fonction générale comme timeIt1 , car timeIt est corrigé à l'aide de R.curry .
Je n'ai pas l'intention de discuter de la coriculisation dans ce post, mais le code suivant démontre l'utilisation principale de la coriculisation:
const f = r.curry ((x, y) => x + y) f (1, 10) // == 11f (1) (10) // == 11Const Plus1 = f (1) plus1 (10) // == 11
D'un autre côté, il y a plusieurs problèmes avec TimeIt mis en œuvre de cette manière:
(... args) => {const t1 = date.now () rappel (... args) report (t1 - t0, ... args)} Il s'agit d'une fonction anonyme (également connue sous le nom de lambda, rappel) qui est appelée après l'exécution de la fonction d'origine de manière asynchrone. Le principal problème est que cette fonction n'a pas de mécanisme pour gérer les exceptions. Si callback lance une exception, report ne sera jamais appelé.
Nous pouvons ajouter un try / catch à cette fonction lambda , mais la racine du problème est que callback et report sont deux fonctions void , et elles ne sont pas associées. timeIt contient deux continuations ( report et callback ). Si nous enregistrons simplement le temps d'exécution sous console ou si nous sommes sûrs que ni report ni callback ne lancent des exceptions, alors tout va bien. Mais si nous voulons effectuer un comportement en fonction des résultats de l'analyse (l'échelle dite automatique), nous devons renforcer et clarifier la séquence de continuation de notre programme.
D'accord, j'espère que le contenu complet de cet article sera utile à l'étude et au travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer.