ReferenceError: Cannot access before initialization circular dependency - javascript

In the simple example below im getting the following error :
ReferenceError: Cannot access 'shared' before initialization
but if i change the export default 2 to a function it will work. Why is this behaviour?
index.js
import a from "./testA.js";
export default 2;
testA.js
import shared from "./index.js";
console.log(shared);
export default function () {}

I checked this both with webpack (code transpiled to es5) and with native modules in Chrome. With transpiled code it just logs undefined.
It only gives an error with native modules no matter if the export is a function or number.
This is because, as the error implies, the default export of index.js isn't initialized by the time you're trying to console.log it.
It's equivalent to doing something like:
console.log(a);
const a = 2;
shared will be initialized when 2nd line in index.js is executed, but the execution of index.js stops on line 1 and waits till execution of testA.js is done.
When compiled to es5, there's a different problem because the partially completed module is passed to another, so whatever wasn't initialized by that time ends up as undefined.

Related

Problem in javascript import/export used in webpack

Is there any problm is the following steps.
1- Suppose i have a js file rough1.js with the code shown below
export function exp1(a,b) {
return a * b
}
2- I've another file rough2.js
export var x = exp1(1,2);
3- In index.js I imported previous two script as shown below
import {exp1} from './rough1';
import {x} from './rough2';
Now when i perform npm run build it shows in console that
Uncaught ReferenceError: exp1 is not defined
So how to resolve this issue? How i will get my index.js to work with no error (recognising the imported value from one file in another)?
As far as i can see you need to use this statement in rouge2.js
import {exp1} from './rough1';
Thanks

Correct way to export/define functions in Electron's Renderer

I have a JS file that I'm importing into my Electron's "main" (or background process), app.js, using require (eg: const myJS = require("./pathToMyJS/myJS");)
Contents of myJS.js:
module.exports = {
mFunc: function mFunc(param1) {
...
}
};
And I can use mFunc in app.js as myJS.mFunc(param1); & everything's great.
Then, I tried to follow the same process for the "renderer" JS. So my renderer.js now imports const myOtherJS = require("./myJS/myOtherJS"); where this other JS file follows the exact same module.exports logic as myJS.
And the root HTML (app.html) declares the renderer as <script defer src="./renderer/renderer.js"></script>.
But on launch, I get:
Uncaught TypeError: Cannot set property 'exports' of undefined
at renderer.js? [sm]:34
Searching online, I came across this answer that mentions that the AMD way could be used instead of the commonJS way. So I tried the following: (not sure whether this is syntactically correct!)
define(
["renderer"],
function rFunc(param1) {
... }
)
But that fails with:
Uncaught ReferenceError: define is not defined
So what's the correct way to have functions defined for export when using them in the renderer? What I've been doing so far is just to write the functions in their own JS files (eg: function func1() { ...}) & declaring all of these files in the app.html as <script defer src="./funcFile1.js"></script>.
Turns out, I was just exporting incorrectly. modules.export was the point of failure as modules is undefined on the renderer.
Instead, if I do the following to export individual functions:
// ./myJS/myOtherJS.js
export function rFunc() { ...}
And then import into my renderer.js like:
import { rFunc } from './myJS/myOtherJS';
rFunc();
Things work as I originally expected.
This Google Developers Primer on modules was useful in understanding the concepts.
AMD is not provided by node.js by default. It's used by Require.js and other FWs. Here is a link on how you can use it with node:
https://requirejs.org/docs/node.html

How to port an ES6 require() statement to typescript

We have been able to ported all the code for from JS/ES6 project to typescript 3.x but we can't seem to get the following file ported correctly.
The short version of file looks like this:
index.js (original):
export const Log = require('./src/Log');
export const OidcClient = require('./src/OidcClient');
export default {
Log,
OidcClient
};
index.ts (ported):
import Log from './src/Log';
import { OidcClient } from './src/OidcClient';
export default {
Log,
OidcClient
};
The problem appears to be with the import LOG from './src/Log' vs. the export const Log = require('./src/Log'); statement. If we change the source file to use export LOG from './src/Log'; then the Log is undefined in the calling script file, just like the problem we are seeing in the ported version.
Intellisense, for the source file, states that the exported OidcClient statement is defined as
(property) OidcClient: typeof import("c:/.../src/OidcClient").
Whereas the ported version of the OidcClient statement is defined as
(property) OidcClient: typeof OidcClient.
How do we make this work from a TypeScript file?
For completeness
We are using webpack and built the output as a library, with these output settings:
libraryTarget: 'var',
library:'Oidc'
Thus the JS client should use the module like: Oidc.Log.Error(message). But the problem was Oidc.Log is undefine.
The clue
In the browser's debugger we noticed that Oidc is defined as a Module, which is what we expected, but it had a mysterious property called default which had everything we wanted within it. Okay, how to remove the default property and apply everything in it's part object, the Oidc module?
After 4 days of trial and error, we found the solution.
Solution
The documentation, and everything we could find, stated we should use:
export default { Log, OidcClient }
Out of desperation we finally tried removing the default keyword, as in:
export { Log, OidcClient }
and guess what? It worked!!
No more mysterious default property and all the types live off of the Oidc module as expected!

Export default is also exporting code the exported function is being used in

I have this function:
// menuAnimate() adds/removes the classes for the mobile menu animation
export default function menuAnimate() {...}
which I am importing into my mocha test file like so:
import { menuAnimate } from '../src/scripts/nav';
However, when I run a test involving menuAnimate, I get an error this error:
/Users/johnsoct/Dropbox/Development/andybeverlyschool/src/scripts/nav.js:67
navToggle.addEventListener('click', menuAnimate);
TypeError: Cannot read property 'addEventListener' of null
This error is being thrown from code further down within nav.js.
navToggle.addEventListener('click', menuAnimate);
How can I export only the function block?
import { menuAnimate } from '../src/scripts/nav';
says "import this file, and let me access one function from it". There's no importing of only part of a file. If you don't want other stuff in that file to run, then you should split the code into two separate files, or rearchitect your code such that it doesn't run when the file loads.
navToggle.addEventListener('click', menuAnimate);
specifically seems like something I'd never expect to execute when the file loads. If you need to bind a listener, you should export a function from your module to do it, then call that function when you actually want the listener to be bound. e.g.
export function initNav() {
var navToggle = ...
navToggle.addEventListener('click', menuAnimate);
}
The top-level scope of a module should have pretty minimal logic of its own. Loading a module on its own isn't something that should have sideeffects like adding an event listener. Pretty much the only time you'd want that is in the initial application JS file.
Also, as mentioned in a comment, since you do
export default ...
you'd want to do
import menuAnimate from
or keep the import you have and do
export function menuAnimate() {...}
without the default.

unusual unexpected token in webpack

I have a file call scripts.js and it merely do var main = require('./main');
and my main.js is at the same level, it has
module.exports = {
console.log("hello");
}
I do webpack in my terminal I got unexpected token?
You can not include function executions into a javascript object (you are exporting an object), you need to export a function to achieve this
module.exports = function() {
console.log("hello");
}
And from your file where you require the export
var main = require('./main')(); // Add () to execute the function that you obtained
UPDATE:
You are executing console.log() in your main.js file, think that you can simply require some script without exporting nothing, and that file should be executed. For example you can put console.log("hello") without all the module.exports thing and the code should be executed, but when you check the value of your main variable (in the file where you do the require), you probably would not find anything useful.
You can also export a function(like in the code i send before) and then execute that function later, there's many ways to aproach this, I recommend you to google a bit about how module export works and how can you use it
You can check more about module.exports here https://www.sitepoint.com/understanding-module-exports-exports-node-js/, you are using it for the browser, but this examples for node should be usefull anyways

Categories

Resources