I have code basically like this in one file, index.js:
module.exports = {
const processHandler = require("myOtherFile.js");
cp = require("child_process");
cp.fork(pathOfCodeForFork);
cp.send("message");
}
In another file (myOtherFile.js) I have:
process.on("message", function(msg) {
console.log("here is the message " + msg);
}
The file loads but the code inside the process.on block never executes. Would really appreciate some guidance. New to child processes and probably not setting this up correctly.
So I asked this question, but I figured out the issue and wanted to post for anyone else struggling with this (and ask a follow-up). It turns out that pulling out the require for the myOtherFile.js from the module causes this to work (so, place const processHandler = require("myOtherFile.js"); above the module code altogether). The follow up, is I am not sure why? Is the reference to process different inside and outside the module? Or is this a circular requires issue somehow? Is this about the order in which things get run? Something else?
Related
I'm using Webdriver.io to run tests on a large number of pages. Because all the specs for the pages are in a JSON file, I have a special class that sets up the test. It looks like this:
module.exports = class PageTester {
suiteName = '';
browser = {};
constructor (suiteName, browser) {
this.suiteName = suiteName;
this.browser = browser;
}
testModel(currentModel) {
describe(this.suiteName + ' endpoint ' + currentModel.url, () => {
this.browser.url(currentModel.url);
/* it() statements for the test */
});
}
}
Then in my specs folder I have a file that loads the JSON and plugs it into the PageTester class, like this:
const PageTester = require('../modules/PageTester');
const models = require('/path/to/some/file.json');
const pageTester = new PageTester('Some Name', browser);
for (const modelName in models) {
pageTester.testModel(models[modelName]);
}
When I run this code, WebdriverIO gives me the following warning:
WARN #wdio/mocha-framework: Unable to load spec files quite likely because they rely on `browser` object that is not fully initialised.
`browser` object has only `capabilities` and some flags like `isMobile`.
Helper files that use other `browser` commands have to be moved to `before` hook.
Spec file(s): /suite/test/specs/test.js
All the tests seem to run fine, so I don't actually understand what this warning is complaining about and what negative consequences ignoring it may have. So I would like to a) understand why this is happening and b) how it would be possible to get rid of this warning given the way my code is set up.
In my case, I resolve it by fixing the path for the require files. I noticed that my path was wrong. But the error that wdio throws is not really helpful. :/
you can only interact with browser object inside it blocks because it is not fully accessible before the browser session is started.
See https://webdriver.io/blog/2019/11/01/spec-filtering.html for details.
You simply should ensure your spec file and respective page file are kept on a similar folder structure.
I'm currently running a heavy computation (i.e. generating a Monte Carlo tree), which is an expensive operation. I only have a few seconds to build as big of a tree as I can, so I am using subprocesses in Node.js in order to build multiple trees, and then aggregate their data together to make a more informed decision.
I understand that subprocesses do not share information/memory, and I need to use modules within these subprocesses that are located in a file, called "Epilog.js" on my machine.
When I run functions that are in epilog.js from the main file, it works just fine. But all of my functions that are in my worker threads return absolutely nothing.
I have tested to make sure that the parameters of the functions I am trying to use in "epilog.js" aren't empty, and they're not. The problem isn't in the parameter.
I have also tested to see what happens if I simply don't import, and instead of just outputting an undefined array, I get an error saying that there is no function called "findroles".
//My main thread.
var fs = require('fs');
eval(fs.readFileSync('epilog.js') + '');
var process = fork('./buildGraph.js');
process.send({library});
//My worker thread.
//buildGraph.js
var fs = require('fs');
eval(fs.readFileSync('epilog.js') + '');
// receive message from master process
process.on('message', async(message) => {
library = message["library"];
console.log(findroles(library));
// findroles(library) is a function that is defined in epilog.js,
//and this outputs an array of "roles" given a parameter,library.
// For some reason this function outputs [], rather than giving me
// all of the roles. If I run this exact line from my main thread,
// it doesn't give any errors and outputs the right array:
// e.g. ['red', 'white'].
});
I expect to get not the empty array, but [red, white], as I do if I were to run the same line in the main thread. Does anyone have an idea as to the inconsistency of the functions? I'm very new to node.js and this isn't a class focused too much on software engineering in JavaScript, so I'd appreciate if someone can dumb down what is going on, as this is all very new to me.
If your script does not find the function called findroles then there is a problem with the importing method. Using the eval function for importing is not the normal way of importing modules. Try something like this:
// buildGraph.js
const epilog = require("./epilog.js");
......
console.log(epilog.findroles(library));
then epilog.js
exports.findroles = function (library) {
// function content
}
You can find more info here:
https://www.w3schools.com/nodejs/nodejs_modules.asp
Base on the document and example here, everything seem correct but I think the problem come from this line:
var process = fork('./buildGraph.js');
you might override the original process.
try to change it to
const n = fork('./buildGraph.js');
We've found a fairly insidious problem with a Durandaljs 2.1 application which has not really come to light previously.
Essentially the error we have received appeared to be a 404 error. However we have added a little additional error tracking and found what appears to be a timing error.
The modification we performed is as follows
viewEngine.createFallbackView = function (viewId, requirePath, err) {
var that = this,
message = 'View Not Found. Searched for "' + viewId + '" via path "' + requirePath + '". Error: ' + err.message;
return system.defer(function (dfd) {
dfd.resolve(that.processMarkup('<div class="durandal-view-404">' + message + '</div>'));
}).promise();
};
When trying to load a specific view We get the view not found warning and the Javascript for the view is then displayed. This occurs very sporadically when the code is not minified, although seems more common on mobile devices such as Iphones. This does not occur in development atall.
However once I've used Grunt to minify the javascript the error occurs every single time in dev environment. This leads me to suspect a most insidious timing error. Has anyone else come accross this kind of problem and got any suggestions for how we might fix this. We're using Durandaljs 2.1.
The error that we receive is of the form
View Not Found. Searched for "views/stationDetails(router,dataManager){var _this=this;[Javascript ViewModelCode].fail(function(){}).promise.html".
The app always loads fine when going to the default page, however the error occurs on a separate view.
Just had another review of the code in this view. The actual durandal activate function returns a promise object, which could be relevant to the problem?
Any help gratefully received.
Ok I've done some more playing and realised there is more info relevant to this post. We are using typescript for our viewModels and this issue is related to using either instanced viewModels vs a Singleton.
So in most cases we have a singleton viewModel that we have defined as follows:
export class viewModelObject {
constructor() { }
}
define([], () => {
return new viewModelObject();
});
In the case where we need an instanced viewModel we've done the following:
define([], () => {
return () => {
return new viewModelObject();
};
});
I haven't seen this before. Would it be possible for you to send me a simplest possible solution that reproduces the bug? I can tell you that the way you are using instanced view-models is irregular. I would expect you to return the constructor function itself. Perhaps that is the source of the issue?
I read a lot about Express / SocketIO and that's crazy how rarely you get some other example than a "Hello" transmitted directly from the app.js. The problem is it doesn't work like that in the real world ... I'm actually desperate on a logic problem which seems far away from what the web give me, that's why I wanted to point this out, I'm sure asking will be the solution ! :)
I'm refactoring my app (because there were many mistakes like using the global scope to put libs, etc.) ; Let's say I've got a huge system based on SocketIO and NodeJS. There's a loader in the app.js which starts the socket system.
When someone join the app it require() another module : it initializes many socket.on() which are loaded dynamically and go to some /*_socket.js files in a folder. Each function in those modules represent a socket listener, then it's way easier to call it from the front-end, might look like this :
// Will call `user_socket.js` and method `try_to_signin(some params)`
Queries.emit_socket('user.try_to_signin', {some params});
The system itself works really well. But there's a catch : the module that will load all those files which understand what the front-end has sent also transmit libraries linked with req/res (sessions, cookies, others...) and must do it, because the called methods are the core of the app and very often need those libraries.
In the previous example we obviously need to check if the user isn't already logged-in.
// The *_socket.js file looks like this :
var $h = require(__ROOT__ + '/api/helpers');
module.exports = function($s, $w) {
var user_process = require(__ROOT__ + '/api/processes/user_process')($s, $w);
return {
my_method_called: function(reference, params, callback) {
// Stuff using $s, $w, etc.
}
}
// And it's called this way :
// $s = services (a big object)
// $w = workers (a big object depending on $s)
// They are linked with the req/res from the page when they are instantiated
controller_instance = require('../sockets/'+ controller_name +'_socket')($s, $w);
// After some processes ...
socket_io.on(socket_listener, function (datas, callback) {
// Will call the correct function, etc.
$w.queries.handle_socket($w, controller_name, method_name, datas);
});
The good news : basically, it works.
The bad news : every time I refresh the page, the listeners double themselves because they are in a loop called on page load.
Below, this should have been one line :
So I should put all the socket.on('connection'...) stuff outside the page loading, which means when the server starts ... Yes, but I also need the req/res datas to be able to load the libraries, which I get only when the page is loaded !
It's a programing logic problem, I know I did something wrong but I don't know where to go now, I got this big system which "basically" works but there's like a paradox on the way I did it and I can't figure out how to resolve this ... It's been a couple of hours I'm stuck.
How can I refacto to let the possibility to get the current libraries depending on req/res within a socket.on() call ? Is there a trick ? Should I think about changing completely the way I did it ?
Also, is there another way to do what I want to do ?
Thank you everyone !
NOTE : If I didn't explain well or if you want more code, just tell me :)
EDIT - SOLUTION : As seen above we can use sockets.once(); instead of sockets.on(), or there's also the sockets.removeAllListeners() solution which is less clean.
Try As Below.
io.sockets.once('connection', function(socket) {
io.sockets.emit('new-data', {
channel: 'stdout',
value: data
});
});
Use once instead of on.
This problem is similar as given in the following link.
https://stackoverflow.com/questions/25601064/multiple-socket-io-connections-on-page-refresh/25601075#25601075
I was trying to create an IRC bot written in Javascript + NodeJS. This bot should be able to load plugins while running and should be able to reload the same plugin after changes etc.
What works?
Loading files at runtime + executing its code.
What's wrong?
After loading the same plugin again if still executes my code, but now it happens twice or nth times I load the plugins.
Current code:
bot.match(/\.load/i, function(msg) {
require('./plugins/plug.js')(this);
});
module.exports = function(bot) {
bot.match(/\.ping/i, function(msg) {
msg.reply('pong');
});
So, is there any way to fix my issues and make this work?
P.s. I'm using IRC-JS as a base for this bot.
updated, fixed:
Even changes to that file are ignored, so it must be something like a
cache.
Fixed by clearing the require.cache
require won't reload a file. Once it has been loaded once, it is in memory and it will not reload again. It sounds like you want to leave the bot on and change the contents of the scripts it requires 'on the fly'. You can do that by deleting require.cache. Check out node.js require() cache - possible to invalidate? and http://nodejs.org/api/modules.html#modules_caching
To answer my own question. While loading plugins, I add every object to a global array. This can be easily accessed and deleted afterwards.
function clearplugins() {
require("fs").readdirSync("./plugins/active").forEach(function(file) {
delete require.cache[require.resolve("./plugins/active/" + file)];
});
plugins.forEach(function(obj) {
obj();
});
}
function loadplugins() {
require("fs").readdirSync("./plugins/active").forEach(function(file) {
if(file.slice(-2) == 'js') {
plugins.push(require("./plugins/active/" + file)(bot));
console.log(file+' loaded');
}
});
}