Cant see png in canvas when using array

Trying to convert 18 png images to an ‘animation’ of 18 canvases/contexts. code is self explanatory, i see the png on screen when i don’t use an array (version that is commented out). i don’t see a png when i try to use an array (non commented out version). i have snake0 to 17 .png in same folder as thiscode.html. so the problem is… that… uh… I’d like to see a png on the screen when using an array. Cuz that would be… cool.

i see the red 60x30 fill but it doesnt show png on screen as pasted with an array of canvases/contexts. if u comment out oppositely (single canvas, no array) it does show png on screen.

<!DOCTYPE html> 
<title>png problem</title>
<meta charset="utf-8"/>
<canvas id="canvas" width="700" height="550" oncontextmenu="return false"></canvas>

<script>

function main(){
	if (paused==false){
		ctx.fillStyle='rgb(128,128,128)'
		ctx.fillRect(0,0,canvas.width,canvas.height)
		ctx2.fillStyle='rgb(255,255,255)'
		ctx2.fillRect(0,0,canvas2.width,canvas2.height)
		
		ctx2.drawImage(snakecans[1],0,0) //does not work with array (comment out the opposite line and block below when testing)
		//ctx2.drawImage(snakecan,0,0) //does work (no array)
		
		ctx.drawImage(canvas2,0,0,canvas2.width,canvas2.height,  5,5,canvas2.width,canvas2.height)
	}
}

canvas=document.getElementById('canvas')
ctx=canvas.getContext('2d')
canvas2=document.createElement('canvas')
canvas2.width=540
canvas2.height=540
ctx2=canvas2.getContext('2d')

//does not work (comment out opposite block and line above when testing)
//can't see any png on screen

//i have 18 pngs. i want to put them in 18 'canvases' (so i guess i need 18 contexts too)
snakecans=[]
snakectxs=[]
var i=0
for(i=0;i<18;i++){
	snakecans.push(document.createElement('canvas'))
	snakecans[i].width=60
	snakecans[i].height=30
	snakectxs.push(snakecans[i].getContext('2d'))
	im=new Image()
	im.src='snake'+String(i)+'.png'
	im.onload=function(i,snakectxs){ //you apparently need this onload or the png wont load in time
		console.log(i)
		snakectxs[i].fillStyle='rgb(255,0,0)'
		snakectxs[i].fillRect(0,0,snakecans[i].width,snakecans[i].height)
		snakectxs[i].drawImage(im,0,0)
	}(i,snakectxs) //says 'snakectxs[i] is undefined' unless I put that stuff in parentheses
}



//does work
//can see png on screen
/*
snakecan=document.createElement('canvas')
snakecan.width=60
snakecan.height=30
snakectx=snakecan.getContext('2d')
im=new Image()
im.src='snake'+String(3)+'.png'
im.onload=function(){
	snakectx.drawImage(im,0,0)
}
*/




paused=false
setInterval(main, 1000/60)
</script>

I don’t blame any of you for not answering this… it was nearly unanswerable, but I FOUND the solution. Yes, it took 48 hours of research to merely make an array of animation frames, something that should take 10 seconds. The problem was javascript’s hideous onload function, usually mangling what the i value was supposed to be. I got the answer from here
search for stackoverflow how-to-pass-parameters-into-image-load-event
Anyway, the ONLY answer that worked on that page was the ‘private scope closure’ one. It is a hideous solution I don’t undertand to match the hideous onload function. I mean you pass a variable to onload and it doesn’t even use the variable you send it, unless you cast this david blane private scope closure spell. I have no idea what this beast is, but it is the only solution. You have to use a beastly closure to merely get an array of image frames in javascript, there is no other solution. I almost thought javascript just couldn’t handle variables or loops or something, suspecting the whole language was one giant non-turing complete typo. Apparently the closure ‘freezes’ the current value of i at the time of making the onload function, otherwise onload would use some later value of i. Next time I need to use this insane closure with multiple parenthesis and brackets I surely won’t remember how. Damn, what a mess, well that was a 48 hour delay, maybe I can get back to coding my game until the next catastrophe. Then maybe I can sell it for 2 cents on amazon mechanical turk, the only employer left in this sabotaged economy.

the solution

<script>

function main(){
	ctx.fillStyle='rgb(192,192,192)'
	ctx.fillRect(0,0,canvas.width,canvas.height)
	
	//draw all frames in a column
	for(i=0;i<snakecans.length;i++){
		ctx.drawImage(snakecans[i],0,i*30)
	}
}

canvas=document.getElementById('canvas')
ctx=canvas.getContext('2d')

//works
snakecans=[]
snakectxs=[]
snakeimgs=[]
for(i=0;i<18;i++){
	snakecans.push(document.createElement('canvas'))
	snakecans[i].width=60
	snakecans[i].height=30
	snakectxs.push(snakecans[i].getContext('2d'))
	snakeimgs.push(new Image())
	snakeimgs[i].src='snake'+String(i)+'.png'
	//the ugly function returning function of a private scope closure, the single obscure incomprehensible solution to the problem caused by javascripts onload function
	snakeimgs[i].onload=(function(i){
		return function(){
			snakectxs[i].drawImage(snakeimgs[i],0,0)
		}
	})(i)
}

setInterval(main, 1000/60)
</script>