Say I have a queue class that's executing a series of functions I've already declared:
class DrawQueue{
constructor(interval){
this.sequence = [];
this.interval=interval?interval:50;
}
addFunction=(fn)=>{
this.sequence.push(fn);
//throw exception here if not a function
};
execFunctions = ()=>{
let intvl = setInterval(
()=>{
const fn = this.sequence.shift();
//clear interval & return here if not a function
fn.call();
},
this.interval
)
}
}
Now I want to pass it a series of functions that have some values calculated inside them: //I have a single count variable here but the code I'm running is being generated by a user who might have any number of variables that are being updated let count = 0; let counterDiv = document.querySelector('#counter') let dq = new DrawQueue(1000); function startCount(){ //call when window's loaded let countFn=(()=> { let innerFn= function(){ let str = (function(){ return count.toString() })(); counterDiv.innerHTML=str; } //imagine that any number of count variables might be being updated somewhere in the function count++; dq.addFunction(innerFn); })
while(count<10){
countFn();
}
dq.execFunctions();
}
Right now this immediately sets the counter div to 10, and then keeps setting it to 10 ten more times. But I want to assign the str
variable's value before I pass the functions. So the first function I pass sets the counter to 1, then 2 and so on.
I was trying to set the let str= function(...
using an iife, but that didn't work.
One solution that I know would work is to make the whole function a string and then run it with eval
but I really do not want to use eval
unless I absolutely have to.
Is there any other way to pass these functions with certain variables already "locked in", meaning they're assigned before the function is placed in the queue?
UPDATE: To clarify, this is just a simplified version of a more complex example. In the actual example, the code is dynamically generated by another user, so in addition to 'count' any number of other values might need to be evaluated. So passing the count
variable, as several good answers have suggested, is not going to work.
FURTHER CLARIFICATION: What I'm saying above is that because the user could be generating any number of variables that will be updated as the code runs, I can't pass those variables as arguments. (imagine there might be a count2
, count3
...countn
and I don't know how many or where they'll be used or updated in the code.
FURTHER UPDATE: so a commenter wants to see the code in which this applies so here goes. It is an application using Blockly and P5 play, where users will be making code with blocks to move a sprite. So the code for the blocks might be something like this (yes this code is really ugly because it's just a test, but you asked to see it):
function moveForward(sprite){
let dir = ship.rotation* (Math.PI / 180);
let deltaX = Math.cos(dir)*5;
let deltaY = Math.sin(dir)*5;
let newX = ship.position.x + deltaX;
let newY = ship.position.y + deltaY;
ship.position.x=newX;
ship.position.y=newY;
redraw();
}
function moveBackward(sprite){
let dir = ship.rotation* (Math.PI / 180);
let deltaX = Math.cos(dir)*5;
let deltaY = Math.sin(dir)*5;
let newX = ship.position.x - deltaX;
let newY = ship.position.y - deltaY;
ship.position.x=newX;
ship.position.y=newY;
redraw();
}
function turnLeft(sprite){
let newDir=ship.rotation-90;
ship.rotation=newDir;
redraw();
}
function turnRight(sprite){
let newDir=ship.rotation+90;
ship.rotation=newDir;
redraw();
}
There will be any number of other sprites, each with 20 or so properties that could be updated.
Now if I just put all these functions in a row, the sprite will just immediately jump to where the code would put it. Because, you know, normally we want computers to do things as fast as they can.
But since this is made for teaching, I want the user to see the canvas updating step by step, with a delay between each redraw. That means every sprite will have its x and y coordinates, along with color and rotation and a bunch of other things, change slowly.
So the purpose of the DrawQueue to execute the drawing update steps slowly with a setInterval and update the canvas at any interval I want. I can't just run every single command with a setInterval because there could be logic or loops in there. The only thing I want to go in the interval is the updates to the canvas, anything else can happen as fast as it wants.
So imagine the four functions I provided above, along with any number of other functions and modifications to the properties of any number of other sprites or properties of the canvas.