I am using web workers in my React application with a helper class that looks like this:
export class WebWorker {
constructor(worker) {
const code = worker.toString();
const blob = new Blob(["(" + code + ")()"]);
return new Worker(URL.createObjectURL(blob));
}}
The worker looks something like:
export default () => {
self.addEventListener('message', function (e) {
switch (e.data.event) {
case 'start':
// Start back ground task
break;
case 'stop':
// Stop background task
break;
}
}, false);
Then I am able to create the worker using
let sessionWorker = new WebWorker(SessionWorker);
sessionWorker.postMessage({event: "start"})
This works fine, however I now need to use a SharedWorker and I am having trouble getting it to work. All of the resources I've found show regular web workers. There is this SO Question Using Shared Worker in React but it doesn't work for me. It actually looks identical to my regular WebWorker code, but this doesn't work because SharedWorkers require that you implement an onconnect function, and I don't understand how to do that. Non-react examples that I've found show the worker script as:
onconnect = function(e) {
var port = e.ports[0];
port.onmessage = function(e) {
var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
port.postMessage(workerResult);
}
}
but if I put that in my worker js file and follow the same pattern using the WebWorker helper, the worker.toString() just returns [object Window] and it never gets executed. I don't understand how to create an 'onconnect' function that will get called. I've tried variations like this:
import React from 'react';
self.onconnect = (e) => {
var port = e.ports[0];
console.log("test log");
port.onmessage = function(e) {
console.log("Message received ", e)
port.postMessage("test");
}
}
export default self;
Ultimately nothing works for me. Clearly I do not understand exports at all in Javascript. If I just export a function called onconnect it never gets called, clearly the onconnect has to belong to some sort of class-like context (like Window or Self) but I don't understand what is needed
Thankyou,
Troy.
I have a problem with my webpack project, so I was trying to import one class to another and instantiate it but suddenly an error appear in my console and my program stopped working, it was this:
Uncaught ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
This is the code of the class were I am trying to import my another class (that is PopUpPlugin):
import PopupPlugin from './popupPlugin.js';
export const addSearchBtnEvent = (weatherUI) => {
const searchBtn = document.querySelector('.weather__search');
searchBtn.addEventListener('click', () => {
weatherUI.style.opacity = '1';
weatherUI.style.visibility = 'visible';
})
}
export const addSearchExitEvent = (weatherUI) => {
const weatherExit = document.querySelector('.weather__search-exit');
weatherExit.addEventListener('click', () => {
weatherUI.style.opacity = '0';
weatherUI.style.visibility = 'hidden';
})
}
const popupObj = new PopupPlugin();
class searchDashboard {
constructor() {
}
setInputEvent() {
const inputSearch = document.querySelector('.weather__city-search');
const inputSearchBtn = document.querySelector('.weather__search-btn');
inputSearchBtn.addEventListener('click', () => {
const inputSearchVal = inputSearch.value;
this.validateStr(inputSearchVal);
});
}
validateStr() {
const onlyLettersAndSpaces = /^[a-zA-Z][a-zA-Z\s]*$/;
if(str.trim().length > 0 && str.match(onlyLettersAndSpaces)) {
const strValue = str.toLowerCase().trim().replace(' ', '+');
this.popupObj.searchCoincidences(strValue, 'weather__search-ui');
}
}
}
export default searchDashboard;
I don't actually know why this is happening, I also tried to instantiate it inside the constructor and it worked but it sended me the error of an stack overflow.
PD: If someone needs it here is the code of the PopupPlugin. (Here is what was working to me that was instantiating the class inside the constructor until the stack overflow error appeared)
import ManageWeatherDashboard from './manageWeatherDashboard.js';
import { getFetch, repeatAppend } from './weatherHelpers.js';
class popupPlugin {
constructor() {
this.manageWeatherDashboardObj = new ManageWeatherDashboard();
}
validateStr(str) {
const onlyLettersAndSpaces = /^[a-zA-Z][a-zA-Z\s]*$/;
if(str.trim().length > 0 && str.match(onlyLettersAndSpaces)) {
const strValue = str.toLowerCase().trim().replace(' ', '+');
return strValue;
}
}
searchCoincidences(val, parent) {
getFetch(`https://www.metaweather.com/api/location/search/?query=${val}`)
.then(res => res.text())
.then(data => {
const parentResults = document.querySelector('.'+parent);
parentResults.innerHTML = '';
const dataArr = JSON.parse(data)
if(dataArr.length >= 15) {
let resVal;
for(let i = 0; i <= 15; i++) {
resVal = this.addDOMResultCoincidences(parent, dataArr[i].title,
dataArr[i].woeid);
}
this.whenClickCoincidence(resVal);
} else {
let resVal;
dataArr.forEach(el => {
resVal = this.addDOMResultCoincidences(parent, el.title, el.woeid);
})
this.whenClickCoincidence(resVal);
}
})
}
addDOMResultCoincidences(parentBlock, name, id) {
const args = Array.from(arguments);
if(args[0] === 'popup__results') {
const popupResults = document.querySelector('.popup__results');
const divResult = document.createElement('div');
divResult.className = 'popup__result';
divResult.setAttribute('data-woeid', id);
const spanResultName = document.createElement('span');
spanResultName.className = 'popup__result-name';
const cityReturn = document.createTextNode(args[1]);
spanResultName.appendChild(cityReturn);
divResult.appendChild(spanResultName);
popupResults.prepend(divResult);
return divResult;
}
if(args[0] === 'weather__search-ui') {
const weatherUI = document.querySelector('.weather__search-ui');
const divResult = document.createElement('div');
divResult.className = 'weather__search-result';
divResult.setAttribute('data-woeid', id);
const spanResultName = document.createElement('span');
const spanResultNameText = document.createTextNode(args[1]);
spanResultName.className = 'weather__city-result';
spanResultName.appendChild(spanResultNameText);
const iconResult = document.createElement('i');
iconResult.className = 'fa fa-arrow-right weather__go-result';
repeatAppend([spanResultName, iconResult], divResult);
weatherUI.appendChild(divResult);
return divResult;
}
}
// When click a coincidence in search field
whenClickCoincidence(el) {
const woeId = el.getAttribute('data-woeid');
el.addEventListener('click', () => {
let handler = 0;
if(handler === 0) {
getFetch(`https://www.metaweather.com/api/location/${woeId}/`)
.then(res => res.json())
.then(data => {
const popup = document.querySelector('.popup');
const weatherNext6Days = data.consolidated_weather;
this.manageWeatherDashboardObj.changeWeatherBar(weatherNext6Days[0], data.title);
weatherNext6Days.slice(1, 6).forEach(el => {
this.manageWeatherDashboardObj.nextFiveDays(el);
})
this.manageWeatherDashboardObj.updateStadistics(weatherNext6Days[0]);
popup.style.opacity = '0';
popup.style.visibility = 'hidden';
})
}
handler += 1;
})
}
}
export default popupPlugin;
This might be caused by a cyclic dependencies (i.e. moduleA imports module B and vice versa at the same time). Take a deeper look at your code.
I faced the same issue when I moved the import statement for the redux store below some import of a local module that was dealing with some reducer reference from of the store. Moving the import store from ./store upwards resolved this issue for me.
Try fixing the order of imports in your files.
Had this problem, after upgrading from webpack 4 to webpack 5, and, yes, it was a circular dependency in my case.
Furthermore I found this blog How to Eliminate Circular Dependencies from Your JavaScript Project which led me to https://github.com/aackerman/circular-dependency-plugin
Plopped the plugin into my webpack dev config, as per sample on github, then spent some time reading its output figuring out where I went wrong. Fixing things was pretty easy once I knew the problem - it had been a pretty basic error.
circular-dependency-plugin#5.2.2 works on webpack 4 apparently, and I can confirm it works on webpack#5.73.0 as well. Saved me lots of time :-) You can take it out of webpack dev config after it's done its work.
In my case, it was due to circular import. Meaning, that two modules are exporting and importing contents form each other
For anyone whose issue is not a circular dependency, it could also be a missing import.
In my case, using Material UI 5, I forgot the line import { styled } from "#mui/styles";, which gave me this error:
Uncaught ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
instead of the usual ReferenceError: MyModule is not defined missing import error.
Using my IDE auto import I had something like:
import useStore, { useCart } from "../lib/store"
Everything was working fine for awhile! But then I got the same error until I changed my import to be like this:
import { useStore, useCart } from "../lib/store"
in my case, I was just trying to call the dispatch function before the store had fully loaded - i.e. store.dispatch()
Have same issue in nextjs project.
Switching to previous versions or reinstalling node_modules/ - did not help.
Solution - remove build/ directory and restart build.
In my case, it was the entry-point file that used the following syntax:
export default <symbol>;
Maybe because you used circle import.
For me, I used encapsulated axios to request in mobx store, and I also used some data from mobx store in encapsulated axios.
This isn't exactly what's causing the same error to occur for me.
Mine were caused by calling things like useState, useEffect and firebase() outside the main functional Component Block. This is very dumb but I somehow completely missed it.
Hope it helps anyone from the future who had the same problem as mine.
I have a readable store in Svelte that looks like this:
const state = {};
export const channels = readable(state, set => {
let st = state;
let socket = new WebSocket("ws://127.0.0.1:5999");
socket.onmessage = function (event) {
var datastr = event.data.split(':');
st[datastr[0]].value = datastr[1];
st[datastr[0]].timestamp = Date.now();
set(st)
};
return () => {
socket.close()
}
});
When I import it to my Svelte App works. But if I put that App.svelte as my index.svelte running on Sapper, it doesnt work at first. It says error 500 websocket is not defined. Once I reload the page in the browser start to work...
I have try to parse a function that creates the store instead:
export const getChannel = () => {
// here my store
return {...store}
}
and then creating the store inside a onMount() like this:
onMount( ()=> {
const channel = getChannel();
});
But doesnt seem to do the trick... What do I miss?
Note: If a just replace the store by a simple writable, and create the websocket onMount(), it works without any problem. I just only wanted to put all the communication inside the store as a readable...
In Sapper, code in components (or imported into components) is executed in Node during server-side rendering unless it's put inside onMount (which doesn't run on the server, because there's no 'mounting' happening) or an if (process.browser) {...} block, or something equivalent.
That includes things like references to $channels causing channels.subscribe(...) to be called during initialisation.
Since there's no WebSocket global in Node, creating that subscription will fail. The simplest workaround is probably a simple feature check:
const state = {};
export const channels = readable(state, (set) => {
if (typeof WebSocket === 'undefined') return;
let st = state;
let socket = new WebSocket("ws://127.0.0.1:5999");
socket.onmessage = function (event) {
var datastr = event.data.split(":");
st[datastr[0]].value = datastr[1];
st[datastr[0]].timestamp = Date.now();
set(st);
};
return () => {
socket.close();
};
});
I am trying to create a new state-dependent Audio instance in React. When using require(), I receive the warning, "Critical dependency: the request of a dependency is an expression." I cannot simply import the file since the audio's source is state-dependent. How can I work around this?
The following code gives the error:
playSong = () => {
this.setState(this.state, function(){
let source = require(this.state.songList[this.state.songIndex].src);
let audio = new Audio(source);
audio.play();
});
}
The require() function only seems to work if given a literal.
You cannot require dynamic values, sadly.
You could import all your files into the songList array statically first, and pick the correct one from that:
const songList = [
require('./path/to/song1.mp3'),
require('./path/to/song2.mp3')
];
class MyComponent extends React.Component {
playSong = () => {
let source = songList[this.state.songIndex].src;
let audio = new Audio(source);
audio.play();
};
render () {
// ...
}
}
I've been battling the horrendous Gnome API documentation and came up with this extension:
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const GLib = imports.gi.GLib;
let label;
function init() {
label = new St.Bin({ style_class: 'panel-label' });
let stuff = GLib.spawn_command_line_sync("cat /home/user/temp/hello")[1].toString();
let text = new St.Label({ text: stuff });
label.set_child(text);
}
function enable() {
Main.panel._rightBox.insert_child_at_index(label, 0);
}
function disable() {
Main.panel._rightBox.remove_child(label);
}
This should read whatever is in the hello file and display it in the top panel. However, if I change the contents of the hello file, I have to restart Gnome for that new content to be shown. Now, surely there is a way to do this dynamically but I just couldn't find anything in the documentation. The message in the panel should basically always mirror whatever is in the file. Any ideas how to do this?
You'll want to obtain a Gio.File handle for your hello file, and then monitor it:
let helloFile = Gio.File.new_for_path('/home/user/temp/hello');
let monitor = helloFile.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', function (file, otherFile, eventType) {
// change your UI here
});
This worked for me. It will refresh the label value each 30 seconds.
Add the following import
const Mainloop = imports.mainloop;
In your init method
Mainloop.timeout_add(30000, function () {
let stuff = GLib.spawn_command_line_sync("your_command")[1].toString();
let label = new St.Label({ text: stuff });
button.set_child(label);return true});