Javascript eventListener inside while loop - javascript

I am trying to figure out whether it is possible in Javascript to implement an eventListener into a while loop which can pass a value to a variable inside the loop. I need this to cancel an infinite loop which continiously should send a data frame to a TCP-socket (watchdog). When the socket is closed the loop should end. I use a webworker for this purpose, but it does not work.
Here is the code:
// WebWorker with infinite loop
var check = "true";
let i = 0;
let j = 0;
var returnedEvent;
while (check) {
self.postMessage(i);
onmessage = (event) => {
returnedEvent = event.data;
console.log("worker: " + event.data);
let check = returnedEvent;
}
sleep(100);
}
console.log("loop completed");
function sleep(delay) {
var start = new Date().getTime();
while (new Date().getTime() < start + delay);
}

Related

Convert a sync js function with blocking for loop for websocket updates to html table to async - JS/JQuery

I have a sync function which is blocking the DOM causing updates to slow down in javascript. Is it possible to convert it to an async function?
function setBids(gapPrice)
{
var startBuyPrice = this.bid
gapPrice=parseFloat(gapPrice)
var showMaximum = 15
var startBuyViewPrice = Math.floor(startBuyPrice/gapPrice)*gapPrice
var tmpOrder = {price:null,size:null,total: null}
var currentBuyViewPrice = startBuyViewPrice
var totalBuy=0;
var buys="";
var cntShow = 0
for(var price = startBuyPrice;cntShow<showMaximum;price -= 0.5)
{
if(this.orderBook[price]==undefined)
continue
var tmpSize = this.orderBook[price].size;
if(currentBuyViewPrice>price)
{
currentBuyViewPrice -= gapPrice
tmpOrder['size'] = new Intl.NumberFormat('en-US').format(tmpOrder['size'])
tmpOrder['total'] = new Intl.NumberFormat('en-US').format(totalBuy)
tmpOrder['price'] = new Intl.NumberFormat('en-US').format(tmpOrder['price'].toFixed(1))
if(tmpOrder['price'].indexOf('.')==-1)
tmpOrder['price'] += '.0'
buys+='<tr><td style="color:white !important;">'+tmpOrder['total']+'</td><td style="color:white !important;">'+tmpOrder['size']+'</td><td>'+tmpOrder['price']+'</td></tr>'
tmpOrder = {price:null,size:null,total: null}
cntShow += 1
}
totalBuy+=tmpSize;
if(tmpOrder['price']==null)
{
tmpOrder['price'] = currentBuyViewPrice
tmpOrder['size'] = tmpSize
}
else
{
tmpOrder['size'] += tmpSize
}
}
$(".orderbook-table-bids tbody").html(buys)
}
When websockets update come, this function is called frequently, setting showMaximum to 1 does not have an issue because the loop does not block, anything above 1 causes the page to hang.
Thanks in advance.

javascript stops responding while taking video player current time

var startTime = parent.startTime;
var endTime = parent.endTime;
var divID = '#'+parent.divId;
var description = parent.description;
do {
var currentTime1 = $('video').get(0).currentTime;
if(currentTime1 >= startTime) {
console.log('in if');alert('hi');
parent.$(divID).append(description);
}
setTimeout(function(){$('video').get(0).currentTime = $('video').get(0).currentTime + 1; currentTime1 = parseInt($('video').get(0).currentTime); }, 1000);
} while (currentTime1 <= endTime);
parent.$(divID).empty(); console.log('at end');
the above code stops responding and debuger shows this line var currentTime1 = $('video').get(0).currentTime;
Your code gets to infinite loop, because of
do {
var currentTime1 = $('video').get(0).currentTime;
} while (currentTime1 <= endTime);
It's executed as fast as your browser allows, so it get's stuck, because setTimeout will be executed after 1s and your currentTime1 will never change.
Please change logic - use video events, like timeupdate
var startTime = parent.startTime;
var endTime = parent.endTime;
var divID = '#'+parent.divId;
var description = parent.description;
var myVar = setInterval(check,1000);
function check()
{
var currentTime1 = parseInt($('video').get(0).currentTime);
if(currentTime1 >= parent.endTime)
{
clearInterval(myVar);
parent.$(divID).empty();
}
else if(currentTime1 >= parent.startTime)
{
parent.$(divID).empty();
parent.$(divID).append(description);
}
}
this code works without loop construct. setInterval() works for repeating the action again and again.

How to make Node wait for promise to complete in an infinite while loop?

The snoowrap library returns a promise when a function a call is made using it. I would like for node to wait until the call is complete and then execute its callback function. How can I do that? I've tried different forms of using setTimeout, wait.for library, and other solutions but none have worked.
while(1){
for (var i = 0; i < allowableTimes.length; i++) {
if (new Date().getTime() == allowableTimes[i].getTime()) {
reddit.getHot('aww', {limit: 1}).then(sendToSlack);
}
}
}
function sendToSlack(res){
var url = res[0].url;
var title = res[0].title;
bot.sendWebhook({
username: "bawwt",
icon_emoji: ":smile_cat:",
text: "<" + url + "|" + title + ">",
channel: "#random"
});
}
SOLVED: Here is the solution below that worked for me based on the code in the accepted answer:
if (!err) {
reddit.getHot('aww', {limit: 1}).then(handleReddit);
}
});
function handleReddit(res) {
for (var i = 0; i < allowableTimes.length; i++) {
if (validTime(allowableTimes[i])) {
sendToSlack(res);
}
}
queryReddit();
}
function validTime(allowableTime) {
var date = new Date();
var hour = date.getHours();
var minute = date.getMinutes();
var allowableHour = allowableTime.getHours();
var allowableMinute = allowableTime.getMinutes();
return hour == allowableHour && minute == allowableMinute;
}
function queryReddit() {
setTimeout(function() {reddit.getHot('aww', {limit: 1}).then(handleReddit);}, 60000);
}
function sendToSlack(res){
var url = res[0].url;
var title = res[0].title;
bot.sendWebhook({
username: "bawwt",
icon_emoji: ":smile_cat:",
text: "<" + url + "|" + title + ">",
channel: "#random"
});
}
I believe the reason your callback never gets called is because you never give the node runtime a chance to do that. It's a single thread and you are infinitely using it up with your while(1). It will not have a chance to actually handle the resolving network call that the promise responds to as you are keeping the thread busy with more
As mentioned in the comment: In node, you shouldn't block the rest of the server on a callback. Instead, you should make sendToSlack a recursive function that deals with the callback and fires off another call to reddit.getHot() and get rid of the loop
Conceptual code:
var allowableTimes = 20;
var times = 0;
function handleReddit(res)
{
sendToSlack(res);
times = times + 1;
if(times < allowableTimes)
{
reddit.getHot('aww', {limit: 1}).then(handleReddit);
}
}
reddit.getHot('aww', {limit: 1}).then(handleReddit);
Just off hand code

Variable interval for javascript setInterval based on number of inner loop iterations

I'm trying to automate some actions on a webpage but running into some variable setInterval delay issues. The code pulls a list of elements based on classname and iterates over each one performing an action which dynamically creates new elements on the page, once the elements in collection have been processed the code should re-pull the class elements and iterate over the new collection over and over again.
I want the main delay to be dependant on the number of class elements it pulls from the page and iterates over each time. This code will be run on console in Chrome.
Here was my original working code without a variable delay:
var finishedActions = [];
var actionDelaySec = 5;
var totActionsInLoop;
setInterval( function() {
var pageElementsToActOn = document.getElementsByClassName('classname');
totActions = pageElementsToActOn.length;
for(var i =0; i < pageElementsToActOn.length; i++) {
(function(i){
window.setTimeout(function(){
var actionText = pageElementsToActOn[i].textContent;
if (finishedActions.indexOf(actionText) > -1) {
console.log("already finished action");
} else {
finishedActions.push(actionText);
console.log(actionText);
pageElementsToActOn[i].click();
}
}, i * actionDelaySec * 1000);
}(i));
}
console.log("New Loop");
}, 10000);
My first attempt to just change the 10000 figure to a variable caused a crash due to not being able to change setInterval delays while it's running.
After some research I thought I could recursively nest my function and call itself with a new delay each time.
This code also works but for some reason doesn't change the actual delay each time the main function is called but instead sets the delay to whatever is run on the first iteration:
var finishedActions = [];
var actionDelaySec = 160;
var totActionsInLoop = 5;
var totActionsMade = 0;
var myFunction = function(){
var pageElementsToActOn = document.getElementsByClassName('classname');
totActionsInLoop = pageElementsToActOn.length;
for(var i =0; i < pageElementsToActOn.length; i++) {
(function(i){
window.setTimeout(function(){
var actionText = pageElementsToActOn[i].textContent;
if (finishedActions.indexOf(actionText) > -1) {
console.log("already finished action (" + actionText + ").");
} else {
finishedActions.push(actionText);
console.log(actionText + " Connected At: " + timeStamp());
totActionsMade++;
pageElementsToActOn[i].click();
}
}, i * (actionDelaySec * 1000));
}(i));
}
console.log("New Loop -- Actions on page: " + totActionsInLoop + "-- Total actions finished: " + totActionsMade + " -- Started At: " + timeStamp());
setInterval(myFunction, (totActionsInLoop * (actionDelaySec * 1000)));
};
myFunction();
Can anyone explain to me why the delay isn't changing with each new function call and possibly help me fix the code to work as intended?
Thanks.

Javascript set up Timeout Functions within a for loop

I have a loop that select and object and fades that object in, but when the loop is executed the object id stays at the last entry;
var ordered = Array(elements.length);
var x = 0;
$('#' + that.options.slide_name + '_' + that.nextslide).children().each(function () {
ordered[x] = $(this);
$(this).fadeOut(1);
$(this).attr('id','current_slide_content_' + x);
x++;
});
//fade each element
var time = that.options.fade_speed / ordered.length
var overlap = time / that.options.fade_step;
//time = time + overlap;
var wait = 0;
var num = 0;
var i = null;
var funcs = Array(ordered.length);
for(var a = 0; a < ordered.length; a++){
var w = wait;
var id = $('#current_slide_content_' + a);
window.setTimeout( function (event) {
id.fadeIn(time);
console.log(id);
},w);
//$('#current_slide_content_' + a).fadeIn(time); <-- on its own works, error is with the wait time
wait = time + wait;
}
I narrowed down the error to be in the final loop that actually adds the timeout function.
for(var a = 0; a < ordered.length; a++){
var w = wait;
var id = $('#current_slide_content_' + a);
window.setTimeout( function (event) {
id.fadeIn(time);
console.log(id);
},w);
//$('#current_slide_content_' + a).fadeIn(time); <-- on its own works, error is with the wait time
wait = time + wait;
}
When the id of the element is logged it should be:
foo_0
foo_1
foo_2
But instead it displays as:
foo_2
foo_2
foo_2
I have been on this for days and restarted several times, how do i format the id correctly for each of my Timeout functions?
should try :
window.setTimeout( (function(time_, id_){
return function (event) {
id_.fadeIn(time_);
console.log(id_);
}
})(time,id),w);
This is a closure to save the value of time and id in the scope of the function

Categories