Javascript : workers doesn't do anything onmessage - javascript

I'm trying to create a reminder at a certain date. For that i'm using web-workers with active waiting.
Main.js :
function reminder(message, api) {
var worker = new Worker("./worker.js");
var mesCore = message.body.substr(message.body.indexOf(" ") + 1);
worker.onmessage = function (e) {
api.sendMessage("Ding dong " + mesCore, message.threadID);
};
worker.postMessage(mesCore);
}
worker.js
const cron = require('node-cron');
// reach this line when create worker
onmessage = function(e) {
// never reach this line
console.log(e.data);
var origin = new Date(e.data);
cron.schedule("* * *", function() {
var now = new Date();
if (
origin.getFullYear() == now.getFullYear() &&
origin.getMonth() == now.getMonth() &&
origin.getDate() == now.getDate()
) {
postMessage('message');
return;
}
});
}
Unfortunately the worker never reach the onmessage content. I tried this.onmessage and self.onmessage but it doesn't work. I also tried with "addEventListener" but doesn't work either.
I'm doing this in javascript because the api that I'm using is in javascript so I have no choice.
Thank you if can't help me find a solution

Related

Javascript sharedworker inside for loops

I'm trying to create 7 Javascript shared workers inside a for loop.
My IDE (Pycharm) is giving me a warning for these two variables container-frame and worker:
"Mutable variable is accessible from closure"
Each of these shared worker is communicating with network_worker.js
Below is my JS code:
socket = io.connect('http://' + document.domain + ':4999/layout');
// Set up CSS
for (var i=0; i<player_dict.length; i++) {
var _id = player_dict[i]['_id'];
var container_frame = document.getElementById("container-frame-" + _id);
container_frame.style.display = "none";
setup_communication();
console.log(_id)
var client_id = _id;
var alarm_flag= "";
var alarm_metric="";
if (client_id != null && client_id == 0 && parseInt(location.port) == 4999) { // player_0_hack (for now). Remove and have work properly.
label = "";
} else if (client_id != null){
label = "Service " + (parseInt(location.port) - 5000 + 1);
} else {
label = "Invalid player id";
}
var worker = new SharedWorker('../static/js/network_worker.js', client_id);
console.log(worker);
worker.port.addEventListener('message', worker_callback, false);
window.addEventListener("beforeunload", function () {
worker.port.postMessage('label_close');
});
worker.port.start();
function worker_callback(e) {
console.log(e.data)
if(e.data.type == "update_label") {
console.log(container_frame)
container_frame.style.animationDuration = Math.random() + "s";
}
}
worker.port.postMessage({type: "label_connection", payload: {domain: document.domain, port: location.port, client_id: client_id, label: label}, alarm_flag: alarm_flag, alarm_rate: 1, alarm_metric: alarm_metric});
}
Ultimately what I'm trying to do is animating the container-frame for 7 HTML elements. I'm iterating over these elements using the for loop. These animations happen when an event is triggered from a JS script (update label).
Currently, I have 7 HTML elements. The last element only is having the animation working properly.
My doubt is that when I have put the worker_callback function inside the for loop, the JS compiler became confused about the scope of container_frame but I'm not sure.
Any suggestions please ?
The problem was the two variables container_frame and worker where defined as var not const. Thanks to #Edmund Lee

getCreators() Type Error

I wrote the following function to try to get the user that created the gCal event.
To test this I created an event on calendar and tried to run the script. When the script executes it gets error: "TypeError: Cannot find function getCreators in object CalendarEvent. (line 68, file "Code")".
Any ideas why this is happening? I'm fairly certain getCreators() is a function in object CalendarEvent (Ref:https://developers.google.com/apps-script/reference/calendar/calendar-event#getCreators())
function getuser(instr) {
var today = new Date();
var scriptProperties=PropertiesService.getScriptProperties();
var instrcal= scriptProperties.getProperty(instr);
var event=CalendarApp.getCalendarById(instrcal).getEventsForDay(today);
if (event<1) {
var user= 'None'
}
else if (event>1) {
var user= 'Multiple Users'
}
else {
var user= event.getCreators()
}
return user
}
getEventsForDay returns an array of CalendarEvent objects, all events for that day, even if it is just one.
You'll need to go through the events to find the one you want and then call getCreators().
You can verify this by using
var event=CalendarApp.getCalendarById(instrcal).getEventsForDay(today)[0];
Here the call will work.
The method getEventsForDay(date) gets an array all events that occur on a given day.
Check that you are doing: event < 1 instead of event.length < 1.
Code:
function getuser(instr) {
var today = new Date(),
scriptProperties = PropertiesService.getScriptProperties(),
instrcal = scriptProperties.getProperty(instr),
events = CalendarApp.getCalendarById(instrcal).getEventsForDay(today),
user = 'None';
if (events.length === 1) {
user = events[0].getCreators();
} else if (events.length > 1) {
user = 'Multiple Users';
}
return user;
}

too much string concating at the same time make frontend blocked for a long time,how to optimize?

I use a websocket to listenning the messages from server and show it on front end. but sometimes there are too much message come at a short period time.which made the web browser blocked for a long time. here is my code :
this is the websocket event for receiving message.
$scope.logSocket.on('connect',function(){
console.log("Log socket connected and ready to get log.");
$scope.logSocket.on('log',function(data){
checkStartPhase(data, app);
appendLogText(data);
});
tht code below refresh the data to frontend(using angular js):
var appendLogText = function(log) {
var t = $('#startConsoleContent');
log += '\r\n';
t.append('' + log);
t.scrollTop(t[0].scrollHeight - t.height());
}
and I have to check the status of the log using the function checkAppPhase()
var checkStartPhase = function(data, app) {
var regExp1 = 'Downloaded app package';
var regExp2 = 'Uploading droplet';
var regExp3 = 'Staging failed';
var regExp4 = 'BUILD FAILURE';
var regExp5 = 'Starting app instance';
if( data.indexOf(regExp1) > -1) {
$scope.app_step =2;
} else if(data.indexOf(regExp2) > -1 || data.indexOf(regExp5) > -1) {
$scope.app_step =3;
} else if(data.indexOf(regExp3) > -1 || data.indexOf(regExp4) > -1) {
$scope.stage_failed = true;
$scope.app_step =2;
}
}
Any advice to optimize it would be very good!
What you can do is removing old entries:
var appendLogText = function(log) {
var t = $('#startConsoleContent');
while(t.children().length>=10)
t.find(':first').remove();
t.append('<div>'+log+'</div>');
t.scrollTop(t[0].scrollHeight - t.height());
}
This version of the method would allow only 10 entries on the log.
Demo: http://jsfiddle.net/cu6hcjkk/
Now modify it to the number of entries you want.

Windows Scripting to call other commands?

I was trying my hand at Windows shell scripting using cscript and Javascript. The idea was to take a really long Python command that I was tired of typing into the command line over and over. What I wanted to do was write a script that is much shorter to write the whole Python command into a Windows script and just call the Windows script, which would be a lot less to type. I just don't know how I would go about calling a "command within a command" if that makes sense.
This is probably an easy thing, but I'm an newbie at this so please bear with me!
The idea:
Example original command: python do <something really complicated with a long filepath>
Windows Script: cscript easycommand
<package id = "easycommand">
<job id = "main" >
<script type="text/javascript">
// WHAT GOES HERE TO CALL python do <something really complicated>
WScript.Echo("Success!");
</script>
</job>
</package>
Thanks for all your help!
Here's what I use
function logMessage(msg) {
if (typeof wantLogging != "undefined" && wantLogging) {
WScript.Echo(msg);
}
}
// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var windowStyle = {
hidden : 0,
minimized : 1,
maximized : 2
};
// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var specialFolders = {
windowsFolder : 0,
systemFolder : 1,
temporaryFolder : 2
};
function runShellCmd(command, deleteOutput) {
deleteOutput = deleteOutput || false;
logMessage("RunAppCmd("+command+") ENTER");
var shell = new ActiveXObject("WScript.Shell"),
fso = new ActiveXObject("Scripting.FileSystemObject"),
tmpdir = fso.GetSpecialFolder(specialFolders.temporaryFolder),
tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName()),
rc;
logMessage("shell.Run("+command+")");
// use cmd.exe to redirect the output
rc = shell.Run("%comspec% /c " + command + "> " + tmpFileName,
windowStyle.Hidden, true);
logMessage("shell.Run rc = " + rc);
if (deleteOutput) {
fso.DeleteFile(tmpFileName);
}
return {
rc : rc,
outputfile : (deleteOutput) ? null : tmpFileName
};
}
Here's an example of how to use the above to list the Sites defined in IIS with Appcmd.exe:
var
fso = new ActiveXObject("Scripting.FileSystemObject"),
windir = fso.GetSpecialFolder(specialFolders.WindowsFolder),
r = runShellCmd("%windir%\\system32\\inetsrv\\appcmd.exe list sites");
if (r.rc !== 0) {
// 0x80004005 == E_FAIL
throw {error: "ApplicationException",
message: "shell.run returned nonzero rc ("+r.rc+")",
code: 0x80004005};
}
// results are in r.outputfile
var
textStream = fso.OpenTextFile(r.outputfile, OpenMode.ForReading),
sites = [], item,
re = new RegExp('^SITE "([^"]+)" \\((.+)\\) *$'),
parseOneLine = function(oneLine) {
// each line is like this: APP "kjsksj" (dkjsdkjd)
var tokens = re.exec(oneLine), parts;
if (tokens === null) {
return null;
}
// return the object describing the website
return {
name : tokens[1]
};
};
// Read from the file and parse the results.
while (!textStream.AtEndOfStream) {
item = parseOneLine(textStream.ReadLine()); // you create this...
logMessage(" site: " + item.name);
sites.push(item);
}
textStream.Close();
fso.DeleteFile(r.outputfile);
Well, basically:
Obtain a handle to the shell so you can execute your script
Create the command you want to execute (parameters and all) as a string
Call the Run method on the shell handle, and figure out which window mode you want and also whether you want to wait until the spawned process finishes (probably) or not.
Error handling because Run throws exceptions
At this point it's worth writing a lot of utility functions if ever you need to do it more than once:
// run a command, call: run('C:\Python27\python.exe', 'path/to/script.py', 'arg1', 'arg2') etc.
function run() {
try {
var cmd = "\"" + arguments[0] + "\"";
var arg;
for(var i=1; i< arguments.length; ++i) {
arg = "" + arguments[i];
if(arg.length > 0) {
cmd += arg.charAt(0) == "/" ? (" " + arg) : (" \"" + arg + "\"");
}
}
return getShell().Run(cmd, 1, true); // show window, wait until done
}
catch(oops) {
WScript.Echo("Error: unable to execute shell command:\n"+cmd+
"\nInside directory:\n" + pwd()+
"\nReason:\n"+err_message(oops)+
"\nThis script will exit.");
exit(121);
}
}
// utility which makes an attempt at retrieving error messages from JScript exceptions
function err_message(err_object) {
if(typeof(err_object.message) != 'undefined') {
return err_object.message;
}
if(typeof(err_object.description) != 'undefined') {
return err_object.description;
}
return err_object.name;
}
// don't create new Shell objects each time you call run()
function getShell() {
var sh = WScript.CreateObject("WScript.Shell");
getShell = function() {
return sh;
};
return getShell();
}
For your use case this may be sufficient, but you might want to extend this with routines to change working directory and so on.

Using new Image().src for click tracking

I am attempting to figure out why this click tracker isn't working. The code was written by another developer so I am not entirely sure if this ever did work.
function trackSponsor(o, p) {
(new Image()).src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
return false;
}
From what I can gather is that when this function is called it 'creates a new image' to fire a php script asynchronously. According to Firebug, the request is made however it is 'aborted' ~30ms in. The odd thing is that it will 'sometimes' work as in 1 in every 10+ regardless of the browser.
I would much rather fix this so that it works instead of re-writing it as an ajax request.
Any help is appreciated.
Thanks in advance.
EDIT
Because of tvanfosson's post that got me thinking. I have included the line which calls the click tracker below.
<a onclick="trackSponsor(60, 15077); goToNextStep(1988, 15077, 0); return false;" href="#">view</a>
the goToNextStep() actually changes the page. I am under the impression that it would only be executed after trackSponsor() had finished.
It's actually pretty trivial to rewrite as a get request using jQuery. Rewriting it will certainly help the next developer understand what's happening and might fix your problem. I'd need to know more about the contents of the variables -- perhaps they need to be urlEncoded? -- before I could help you any more on it. You might try urlEncoding them and see what happens.
function trackSponsor(o, p) {
var url = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
$.get(url);
return false;
}
EDIT: you might want to check that another handler isn't redirecting the browser to a new location when the event triggering the tracking is invoked. This would abort any pending requests on the page -- and might allow a few to succeed based on the timing of the requests and if the results are delivered before the page is unloaded.
"(new Image()).src = url;" just asks for browser to hit the url.
You should delay for a 50-100ms in order to be sure that tracking info were sent to the server.
function delay(a) {
for (var b = +new Date, c = 1; 0 < c; c++) {
if (0 == c % 1E3) {
var e = +new Date;
if (b > e) break;
if (e - b > a) break;
}
}
}
function trackSponsor(o, p) {
(new Image()).src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
delay(100);
return false;
}
I poked around Google Analytics’ ga.js, which does use the new Image() method similar to your script.
The only difference that I could see was in how the object is created. Google's script assigns the object to a variable.
var d=new Image(1,1);d.src=f;
Maybe give that a shot?
function trackSponsor(o, p) {
var i = new Image(1,1);
i.src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
return false;
}
It shouldn't make a difference, but is worth a shot.
Maybe try this, for avoiding Garbage Collection to make your log not be lost.
var sendLog = (function () {
var _unique = (function () { /* 产生唯一标识*/
var time = (new Date()).getTime() + '_',
i = 0;
return function () {
return time + (i++);
}
}());
var run = function (url) {
var data = window['imgLogData'] || (window['imgLogData'] = {}),
img = new Image(),
uid = _unique();
data[uid] = img; /* 防止img被垃圾处理*/
img.onload = img.onerror = function () { /* 成功或失败后销毁对象*/
img.onload = img.onerror = null;
img = null;
delete data[uid];
};
img.src = url + '&_cache=' + uid; /* 发送统计内容*/
};
return run;
}());
sendLog('http://log_');

Categories

Resources