web-dev-qa-db-fra.com

Modules ES6: les constantes importées ne sont pas définies au départ; ils deviennent disponibles plus tard

J'utilise des modules ES6 dans mon application JavaScript. Les sources sont compilées avec webpack et babel. Il s'agit d'une version abrégée du fichier qui me cause des problèmes:

export const JUST_FORM = 0;
export const AS_PAGE = 1;

console.log(AS_PAGE); // **

export default function doSomething(mode = AS_PAGE) {
  console.log(mode);
  console.log(JUST_FORM);
}

J'utilise cette fonctionnalité comme vous vous en doutez.

import doSomething, { AS_PAGE } from './doSomething'

console.log(AS_PAGE);

doSomething();

Lorsque j'exécute l'application, elle s'imprime trois fois undefined et une seule fois la valeur attendue AS_PAGE qui est le console.log marqué avec **. Cependant, ceci est imprimé en dernier! Cela montre que:

  • Le AS_PAGE constante, lorsqu'elle est utilisée comme paramètre par défaut pour la fonction doSomething`, n'est pas définie au moment de la définition de la fonction.
  • Le JUST_FORM constante n'est pas définie lorsque doSomething est appelée.
  • Le AS_PAGE constante n'est pas définie lors d'une importation explicite.

Apparemment, ce qui se passe ici, c'est que seule l'exportation default est analysée et évaluée et le reste du fichier est ignoré jusqu'à plus tard. J'importe ce fichier à plusieurs endroits différents dans mon application (qui est assez volumineuse en ce moment) et à un moment donné, ces valeurs deviennent réellement disponibles. A en juger par la sortie de la console, c'est une question de temps, mais il est possible qu'elle ait une raison différente. Évidemment, je fais l'importation de la même manière partout.

Quoi qu'il en soit, j'ai écrit toute ma demande en supposant qu'une fois que j'importe quelque chose, il est immédiatement disponible et je peux l'utiliser dans mon code. J'ai lu (brièvement) comment les modules ES6 devraient fonctionner et je n'ai rien trouvé qui puisse prouver que cette hypothèse est fausse. Et cela a fonctionné jusqu'à présent.

Notez également que le comportement est le même lorsque je l'exécute avec webpack-dev-server ou le compiler en un seul paquet.

Ce comportement est-il vraiment correct? Qu'est-ce qui pourrait en être responsable?

28
tobik

Comme suggéré dans les commentaires, la réponse ici est dépendances circulaires.

Il n'y a en fait aucune dépendance circulaire présente dans le code fourni dans la question (car il s'agit simplement d'un extrait de code simplifié) mais les symptômes sont très clairs.

L'exemple le plus simple d'une dépendance circulaire est lorsque le fichier A importe le fichier B et le fichier B importe A. Malheureusement, ce qui rend ce problème difficile à détecter parfois, c'est que le cercle peut être arbitrairement volumineux, couvrant une énorme quantité de fichiers.

Les dépendances circulaires sont prises en charge dans ES6 et peuvent être utilisées lorsque l'on est assez prudent. Cependant, ma conclusion ici est que les dépendances circulaires sont très souvent le signe de mauvaises décisions de conception. C'était exactement mon cas.

33
tobik