[JS] Fonction qui retourne indefined (this)

Résolu/Fermé
rdbn Messages postés 95 Date d'inscription samedi 3 avril 2021 Statut Membre Dernière intervention 26 décembre 2022 - 20 sept. 2022 à 18:52
rdbn Messages postés 95 Date d'inscription samedi 3 avril 2021 Statut Membre Dernière intervention 26 décembre 2022 - 23 sept. 2022 à 15:43

Bonjour, j'ai créer une fonction pour me retourner true quand celle ci aura atteint 4s, dans la console j'ai bien un retour mais pas pour la fonction j'ai indefined, une explication ? merci.

const Timer = () => {
  const start = Date.now();
  this.timeEnd = setTimeout(() => {
    const millis = Date.now() - start;
    const second = parseInt(`${Math.floor(millis / 1000)}`); 
    if(second === 4) {
      console.log(second) // 4
      return true;
    }
  }, 4000); 
}
console.log(Timer()) // indefined


Windows / Chrome 105.0.0.0

A voir également:

3 réponses

Il y a d'autres problèmes dans votre code et dans ce cas le mieux c'(est de tester le code avec la console du navigateur ouverte+débogueur éventuellement qui indique les erreurs lignes par ligne puis de regarder ligne par ligne où elle est et comment la corriger).

Ici je dirais que si vous utilisez une égalité stricte 'symbole ===' vous n'êtes pas prêt d'avoir ce cas de faigure.

De plus vous ne tenez pas compte de l'explication sur l'objet qui fait que votre constante Timer est une fonction qui ne renvoi rien(pas de valeur return et dans votre cas il faudrait utiliser "return this") donc si vous faites :

var instanceDuneFonction= Timer()

vous n'avez aucunement un résultat exploitable, juste une fonction qui s'exécute et auquel vous ne pouvez avoir aucun accès. En gros ici plutôt que d'avoir une constante et une fonction vous n'avez besoin d'aucun des deux juste utiliser setTImeOut.

C'est la 1ère erreur que j'ai expliqué et je m'étonne que vous montriez la même encore, relisez mes explications qui indiquent plusieurs méthodes pour créer un objet si vous voulez créer un objet(donc utiliser this.attribut='quelque chose' hors de la fonction) mais effectivement l'utilisation d'un objet ou d'une fonction étant inutile pour votre cas(utiliser setTimeOut pour faire une boucle de 4000ms)...

Bref si vous vous voulez utilisez setTimeOut (qui fait une boucle temporelle infini qui va effectuer une action toutes les X millisecondes) et voulez arrêter la boucle à un temps donné(tous les Y millisecondes) il faut une valeur de départ et de fin et utiliser setTimeOut (voir manuel d'utilisation setTimeOut pour ça), le contexte d'éxécution peut varier(dans un objet , une fonction sont deux contextes qui doivent être appelés quand on en a besoin) . Et pour ça que vous ayez ces valeurs accessibles dans la boucle du timer. Donc voir la portée des variables pour cela (ou simplement donner la valeur en paramètres comme c'est le cas d'un de mes exemples):

https://www.delftstack.com/fr/howto/javascript/variable-scope-in-javascript/

1

Pour le problème de l'égalité stricte comme clause d'arrêt de la boucle c'est simplement que le cas ne peut jamais se produire:

si le compteur passe de 3s(3xxx ms tronquées)à 5s(5xxxx ms tronquées) alors la valeur ne sera jamais égale à 4. D'ailleurs pourquoi tronquer la valeur, cela n'apporte juste que moins de précision. Solution :

Utiliser une comparaison du type >3999ms ou >=4secondes.

1
rdbn Messages postés 95 Date d'inscription samedi 3 avril 2021 Statut Membre Dernière intervention 26 décembre 2022
23 sept. 2022 à 15:43

Je pense que vous ne m'avez pas compris sur le faite que je vous ai re montré mon code "érroné" de départ et que j'essayé quand même de vous expliqué comment j'avais réfléchie.. 

sinon j'ai corrigé mon erreur en le remplaçant par celui-ci 

this.timer = setTimeout(() => {
//console.log(4s);
}, 4000)

 simple efficace.

0

Salut,

"undefined" plutôt qui veut dire indéfini en français.

Donc ce que vous essayez d'afficher est simplement indéfini.

Sans analyser votre code en détail(en le testant) on peut dire plusieurs chose:

Vous créez différentes constantes(pourquoi des constantes d'ailleurs? Un intérêt ici? Une constante étant une valeur qui ne peut pas changer cela semble peu adapter ici mais passons).

 
 <span>this</span><span>.</span>timeEnd= "valeur" celle ci est disponible en accédant à l'objet.

Bon venant en à l'autre problème évident:

Vous utilisez la méthode ou fonction setTimeOut donc devez vous plier à son utilisation:

dont la première est égale (const Timer) à une fonction que vous utilisez comme un objet...

Il y a un problème là déjà...il vaudrait mieux choisir l'un ou l'autre pour être clair ne serais ce que pour vous même:

soit vous utilisez une variable(var ou let non forcément une constante qui ne doit pas changer son contenu) qui est une fonction et que vous utilisez comme une fonction soit vous utilisez un objet que vous utilisez comme un objet. La barrière est mince(voire inexistante) entre un objet JS et une fonction JS mais c'est l'utilisation de celle ci qui fait la différence.

Pour être plus clair:

const start = Date.now();

dans une fonction est l'attribution d'une valeur dans le contexte de la fonction uniquement(son instance donc quand la fonction est appelée et au sein de la fonction uniquement voir ce qu'est la portée d'une variable)

quand vous créez un attribut d'objet: vous créez une variable interne à l'objet accessible par l'objet.

this.timeEnd="valeur" indique que this(l'objet en cours ici une fonction) doit pouvoir être accédé.

Or cela n'est clairement pas possible puisque votre fonction ne renvoie rien du tout.

Un exemple qui permettrait d'utiliser cette syntaxe(car il y en plusieurs pour créer un objet) serait du genre:

function ObjetVoiture( marque ){
this.marque = marque;
return this;
}

let renault=ObjetVoiture('renault')/** crée une instance de l'objet voiture qui a pour attribut marrque de la valeur de son paramétre ou constructeur*/
let peugeot=ObjetVoiture('peugeot')/** même chose avec une autre marque */

console.log(renault.marque)//-- affiche 'renault'
console.log(peugeot.marque)//-- affiche 'peugeot'

Bon ce n'est clairement pas la méthode la plus pratique claire ou rapide de créer un objet mais pourquoi pas. Le principe ici est que la fonction crée avec this.attribut un attriibut interne et se renvoie elle même en fin de fonction, donc chaque instance utilise le constructeur de la fonction et permet d'accéder à ses attributs internes.

Une autre façon de faire plus claire qui ne nécessite pas de faire appel à la fonction est simplement de créer un objet littéral ou d'utiliser la méthode objet create(plutôt déprécéies pour cette dernière) ou même d'utiliser le mot clé class pour créer un objet comme dans des langages plus rigoureux.

/** avec un objet littéral*/

function ObjetLitteralVoiture(marque){
let voiture={marque:marque}
return voiture
}//-- ici la fonction renvoie un objet donc c'est l'objet qui est utilisé

let skoda=ObjetLitteralVoiture('skoda');
console.log(skoda.marque)

/** avec Object.create, plutôt à éviter car pas le plus pratique et différent des autres en fait qui nécessite de passer par la méthode constructor*/

let Mercedes=Object.create()
Mercedes.marque='mercédes'
console.log(Mercedes.marque)//--'mercédes'


/** avec class */

class Voiture{
constructor(marque){
this.marque=marque
}
get marque(){return this.marque}
}

let Ford=Voiture('ford')
Ford.marque()//-- 'ford'

Voilà votre code ne fait rien de tout cela et donc ne renvoi rien...normal que rien soit une valeur indéfinie('undefined').

Pour le reste vous n'utilisez pas correctement setTimeOut qui est une fonction ou méthode du langage(accessible par l'objet windows).

Voici comme celle ci s'utilise:

Quand à la mettre dans une variable vous ne mettez que l'instance de la fonction et celle ci ne renvoi que son indidentifiant qui tel quel est inexploitable.

Ici pour un délai de 4000ms setTimeOut suffit largement mais vous avez aussi la méthode requestAnimationFrame qui permet une boucle temporelle beaucoup plus précise, rapide et paramétrable.

Bon en gros pour faire un chrono de 4secondes vous n'avez qu'à lancer un setTimeOut et utiliser clearTimeOut à la fin si c'est dans une fonction et il faudra bien entendu LANCER LA FONCTION POUR L'UTILISER.

function chrono4secondes(){
var timeOutID= setTimeOut(function(){console.log('4secondes sont écoulées'), 4000}
//-- le setTimeOut fait une boucle de 4secondes
clearTimeOut(timeOutID)/** puis on efface la répétition et la fonction qui englobe le setTimeOut se termine.*/
}

chrono4secondes()

/** mais bon dans ce cas d'utilisation la fonction est bien inutile puisque qu'il suffit de faire un setTimeOut puis un clearTimeOut
let timer=setTimeOut(function(){console.log('il s\est écoulé 4s')},4000);
clearTimeOut(timer)

/* l'inverse est nettement plus fréquent et utile, mettre une fonction dans le setTimeOut */

function boucle(limite){
console.log(new Date().getTime())
if(new Date().getTime()>limite){clearTimeOut(timerID)}
}

var debut=new Date().getTime(),
    fin=debut+5000;

var timerID =setTimeOut(()=>boucle(fin), 1000)
/** beaucoup plus simple que votre script quand même et surtout cohérent avec la méthode setTimeOut qui définit un point d'arrêt dans le temps et va le répéter à l'infini tant qu'on ne le supprime pas avec clearInterval(supprime l’intervalle de la répétition du timer) 
*/

0
rdbn Messages postés 95 Date d'inscription samedi 3 avril 2021 Statut Membre Dernière intervention 26 décembre 2022
Modifié le 23 sept. 2022 à 13:52

Bonjour Omake ! Je te remercie d'avoir donné une réponse aussi complète avec des explications clair.

je t'explique quand même comment je percevais mon code..

/* j'utilise des const parce que ce sont des variables qui auront une valeur fixe*/
const Timer = () => {
  const start = Date.now(); 
  /* récupérer le time actuel */
  this.timeEnd = setTimeout(() => {
    const millis = Date.now() - start; 
    /* récupérer le time actuel (dans le timeout donc après 4s) 
    et je lui retire le const start pour obtenir effectivement 4s */
    const second = parseInt(`${Math.floor(millis / 1000)}`); 
    /* je convertie en seconde le résultat */
    if(second === 4) {
       /* je compare les 4s secondes obtenue par rapport à 4 si c'est le cas je return true; */
      return true;
    }
  }, 4000); 
}
console.log(Timer())

et pour le clearTimeout() je l'avais utilisé aussi mais plus bas dans mon code.

Mais bon j'y vois un peu plus clair maintenant entre quand utilisé une fonction ou une méthode (plus dans la logique)..

et effectivement j'ai mal utilisé la methode setTimeout()..

setTimeout sont principe de base c'est de pouvoir lui affecter un délai pourquoi j'ai rajouté un calcul pour obtenir se délai et le comparer un mystère...

0