How to use import in the web worker - javascript

Created an instance of the Worker class in which the file is imported, but an error appears on startup in the console "import declarations may only appear at top level of a module"
Code of the worker call file:
const worker = new Worker('./js/workers/calculateRequestData.js', {
type: 'module',
});
worker.postMessage({ data: '1' });
worker.addEventListener('message', (event) => {
console.log(event.data);
});
worker.addEventListener('error', (error) => {
console.error(error.message);
});
Code of the file calculateRequestData.js
import template from '../Template/template.js';
onmessage = function (e) {
console.log(e.data);
postMessage(e.data);
};
In network files come with the status 304 (if it helps)
Tried to do:
import template from '../Template/template.js' assert { type: 'module' }
self.template = require('../js/Template/template.js // Error: require not found (or does not work, something similar)
self.importScripts('../js/Template/template.js') // The error is the same as in the previous paragraph, only about importScripts.
All of this doesn't work either

The error was in using the "standard" import... from '...'
The worker file turns into one file with a script, where there should be no exports and imports (in the usual form for modules). In order to import a file, or several files, you need to use importScripts() in the worker (you can not use the keyword self). importScripts() "expands" the imported file in the worker file.
In the vue cli, the worker files and all its imported files should be stored not in the src directory, but in public. This is due to the fact that they are not compiled into a common bundle, but a request is made to a specific file.
Example of the correct code:
File with a worker call:
const worker = new Worker('./js/workers/calculateRequestData.js');
worker.postMessage({...});
worker.addEventListener('message', (event) =>
console.error(event.data); // handle message
worker.terminate(); // don't forget to delete worker
});
worker.addEventListener('error', (error) => {
console.error(error.message); // handle error
worker.terminate(); // don't forget to delete worker
});
File calculateRequestData.js
self.importScripts('../Template/template.js');
onmessage = function (e) {
template.calculate(...) // work with imported filse
};
I also ran into a problem when the production build did not work due to the incorrect mime-type ('application/octet-stream') of the worker files and the imported script. This is due to the fact that our server by default have files with such a mime-type, while the browser by default calls the "Save as" modal window. This is treated by specifying in the configuration file for mime types by adding the line 'application/octet-stream' The solution was found here - application/octet-stream mime type issue with codeigniter
Example:
'js' => [
'application/x-javascript',
'text/plain',
'application/octet-stream',
],

Related

Uploading images to AWS S3 bucket - specifying file path for randomly generated file names

I'm working on an automated testing project using PuppeteerJS in headless Chrome and trying to integrate existing screenshot functionality with AWS-SDK to upload images to an AWS S3 bucket on test failure.
The problem i'm having is the sub directories in a screenshots folder and the image file names are generated randomly in another file based on the current date and test environment, and run every time a test runs. The format of the generated directories/files is "screenshots/year/month/day/randomname.png".
The next step in the test is after the screenshots are generated, the folder containing the newly created images should be uploaded to AWS, and I've tried to achieve this using a glob to get every subdirectory and file with a png extension, like "screenshots/**/**/**/*.png", but i get a "no such file or directory" error". The folders/file names will be different everytime the tests run.
I've just started using AWS and I haven't been able to find a specific answer to my problem while researching.
import { PutObjectCommand } from "#aws-sdk/client-s3";
import { s3Client } from "../libs/s3Client.js";
import path from "path";
import fs from "fs";
const file = "../../screenshots/**/**/**/*.png";
const fileStream = fs.createReadStream(file);
// Set the parameters
export const uploadParams = {
Bucket: "bucket-name",
Key: path.basename(file),
// Add the required 'Body' parameter
Body: fileStream,
};
// Upload file to specified bucket.
export const run = async () => {
try {
const data = await s3Client.send(new PutObjectCommand(uploadParams));
console.log("Success", data);
return data; // For unit tests.
} catch (err) {
console.log("Error", err);
}
};
run();
Worked this out with the help of Jarmod. I needed to use the nodeJS:fs module to get the file paths recursively and returns a string which can be passed into the AWS fileStream variable for it to be uploaded to AWS. Jarmod shared the webmound article and i found the coder rocket fuel article hepful also.
https://www.webmound.com/nodejs-get-files-in-directories-recursively/
https://coderrocketfuel.com/article/recursively-list-all-the-files-in-a-directory-using-node-js

Can't find 'path' in worker using Electron & Webpack

My electron app uses a worker to compile WASM in the background (through worker-loader). However, I get the following error when running it:
How would I solve this error? It looks like the module is trying to use path, so I've added the path fallback in Webpack config:
However, this didn't fix my issue
worker.js
import { Essentia, EssentiaWASM } from 'essentia.js';
let essentia = new Essentia(EssentiaWASM);
self.addEventListener('message', (event) => {
console.log(essentia.version);
})

How do I initialize a webworker in NextJS 10?

I have a Next 10 project where I am trying to use WebWorkers. The worker is being initialized like so:
window.RefreshTokenWorker = new Worker(new URL('../refreshToken.worker.js', import.meta.url))
I also have the Worker defined as
self.addEventListener('message', (e) => {
console.info("ON MESSAGE: ", e)
// some logic with e.data
})
Its also being called like this:
const worker = getWorker() // gets worker that is attached at the window level
worker.postMessage('start')
My next.config.js file is defined as
const nextConfig = {
target: 'serverless',
env: getBuildEnvVariables(),
redirects,
rewrites,
images: {
domains: []
},
future: { webpack5: true },
webpack (config) {
config.resolve.alias['#'] = path.join(__dirname, 'src')
return config
}
}
// more definitions
module.exports = nextConfig
The issue I have is the console.info in the Web Worker definition does not receive the message being sent from postMessage on the build version (yarn build && yarn start) but it does on the dev version (yarn dev). Any ways to fix this?
This is not a solution. But can be a messy way to do the job. This turned out to be a nightmare for me.
I have the same setup as yours. I was initializing web worker as you have shown in your question. I got this idea from the nextjs doc itself: https://nextjs.org/docs/messages/webpack5
const newWebWorker = new Worker(new URL('../worker.js', import.meta.url))
Everything working correctly when I work in dev mode. it is picking up the worker.js file correctly and everything looks alright.
But when I build the nextjs and try it, then web worker won't work. When I dive deeply into the issues, I found out that the worker.js chunk file is created directly under the .next folder. It should come under .next/static/chunk/[hash].worker.js ideally.
I could not resolve this issue in a proper way.
So what i did, i placed my worker.js file directly under public directory. I put my worker.js file transpiled and optimized and put the code in the public/worker.js file.
After this, I modified the worker initialization like this:
const newWebWorker = new Worker('/worker.js', { type: 'module' });
it is working in the production build now. I will report once I get a cleaner solution for this.

Firebase FCM on TypeScript: "The script has an unsupported MIME type ('text/html')

I'm trying to implement FCM for my App, and I couldn't yet receive the device token due to this error. Here is the code I'm trying to run:
export const requestFirebaseNotificationPermission = () =>
new Promise((resolve, reject) => {
messaging
.requestPermission()
.then(() => messaging.getToken())
.then((firebaseToken) => {
resolve(firebaseToken);
})
.catch((err) => {
reject(err);
});
});
It seems there might be an issue with th ServiceWorker:
FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope ('http://localhost:3000/firebase-cloud-messaging-push-scope') with script ('http://localhost:3000/firebase-messaging-sw.js'): The script has an unsupported MIME type ('text/html'). (messaging/failed-service-worker-registration).
I found this document which seems to touch this subject, but I confess I didn't understand what needs to be done. Should I create a file named firebase-messaging-sw.js and make it available on my routes? How is that supposed to work?
I have finally found an article more well explained about this topic here, and could enable notifications in my React app following these steps.
As I'm new to this, it was not clear for me that the firebase-messaging-sw.js file should be placed in the "public" directory.

File path in Meteor

I'm having trouble identifying the path to a file in the public directory c:\TEMP\todos\.meteor\local\build\programs\server\public\main.py. Meteor complains the file or directory doesn't exist. Already searched the other postings about the similar issue (e.g., Reading files from a directory inside a meteor app) but didn't help.
Here is the error message.
=> Your application has errors. Waiting for file change.
=> Modified -- restarting.
=> Meteor server restarted
W20151206-04:05:57.893(-5)? (STDERR) Error inside the Async.runSync: ENOENT, no such file or directory 'c:\TEMP\todos\.meteor\local\build\programs\server\public'
Client code
Meteor.call('runPython', function(err, response) {
if(err){
} else {
console.log(response);
}
})
Server code
Meteor.startup( function (){
Meteor.methods({
runPython: function (){
var PythonShell = Meteor.npmRequire('python-shell');
var fs = Meteor.npmRequire('fs');
var runPython = Async.runSync(function (done){
var files = fs.readdirSync('./public/');
// PythonShell.run('main.py', function ... was tried first but Meteor complained that "main.py doesn't exist". So below is a different attempt.
var py = _(files).reject(function(fileName){
return fileName.indexOf('.py') <0;
})
PythonShell.run(py, function (err) {
// PythonShell.run(path.join(py,"main.py") ... was also tried but resulted in the same error
if (err) throw err;
console.log('script running failed');
});
})
return "Success";
}
})
})
All files inside the public folder should be read using '/':
var files = fs.readdirSync('/');
More here: http://docs.meteor.com/#/full/structuringyourapp
For server-side only (might be your case and probably a better solution) you can put everything under the private/ folder and access them by using the Assets API: http://docs.meteor.com/#/full/assets_getText
Clearly I was overthinking it. Specifying a full path to the file was all I needed to do.
PythonShell.run('c:\\project\\public\\main.py', function ...
If your application allows moving the Python script to /private instead of /public, you can take advantage of Meteor's Assets:
Assets allows server code in a Meteor application to access static server assets, which are located in the private subdirectory of an application’s tree. Assets are not processed as source files and are copied directly into your application’s bundle.
e.g. If you move your script to /private/scripts/script.py you can generate the absolute path the Meteor way by doing Assets.absoluteFilePath('scripts/script.py').

Categories