Home > database >  import is undined until I add an extra console.log
import is undined until I add an extra console.log

Time:10-19

I have a Vue3 project(setted up using vue-cli and run as npm run serve) which need a const to be defined so that all services can use it. so my main.js has this constant

// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import "jquery"
import "bootstrap-icons/font/bootstrap-icons.css";

let x = 'google'
export {x};

const app = createApp(App)
app.use(store)
app.use(router)
app.mount("#app")

my services/GetCategoriesService.js is:

import { x } from "../main.js"

console.log(x)

and in my components/footer.vue <script> tag i execute the service script:

import * as $ from 'jquery'
import "../services/GetCategoriesService"

This will result in undefined but adding an extra console.log in my service will make hot reloading(I'm NOT refreshing the page)to run and now i can see two console.log with google then I refresh the page and again see two console.log but with undefined adding another console.log without refreshing result in three google prints, refresh Then I see three undefined which is really weird. I'm using Firefox v 105.0.

NOTE: Using named export of x and console.log x inside a function(which is called from footer.vue) result in same behavior.

CodePudding user response:

You are doing a kind of circular import. To understand what is going on, first, we need to know how the import work.

The import process is divided into 3 steps:

  1. Construction: find, download, and parse all of the files into module records.
  2. Instantiation: find boxes in memory to place all of the exported values in (but don’t fill them in with values yet). Then make both exports and imports point to those boxes in memory. This is called linking.
  3. Evaluation: run the code to fill in the boxes with the variables’ actual values.

The normal case:

// main.js
import { x } from './x'
console.log(x)

// x.js
let x = 1
export {x}

The console.log(x) above will print out 1 because the scenario will appear like below:

  1. Construction: download and parse main.js -> download and parse x.js
  2. Instantiation: find memory for x but don't fill in the value yet
  3. Evaluation: run the code in x.js first (because it does not depend on any module) => set the value for x => run the code in main.js => show the expected value in the console.log because the value x has already been set

The circular import case:

// main.js
import { x } from './x'
console.log(x)
let a = 2
export {a}

// x.js
import {a} from './main'
console.log(a)
let x = 1
export {x}

The console.log(x) in main.js will print out 1 but the console.log(a) in x.js will print out undefined because the x.js will still be run first. Because the JS engine will go down to the bottom of the dependencies graph and execute the module that is at the bottom (usually the module that does not depend on another)

Why does refreshing the page show undefined in the console.log?

Because it follows our scenario above

Why does hot-reload show the expected value in console.log?

Because the hot-reload process just replaces the module that changed. In your case, it is GetCategoriesService.js. So the main.js module is unchanged and its variable is already set the values

This answer is based on the knowledge in this awesome article. Highly recommend reading it for the complete picture

  • Related