先提一个需求:
在打开一个网页游戏时,你需要要等到三张图片全部载成功之后,才能去开始去游戏。
如果写伪代码是:
加载图片();
开始游戏();
从格式上看,这明显是一个同步的代码:加载图片()这个函数执行完成之后,才会去做 ga开始游戏() ,但现在有一个问题,加载图片这件事是异步的。
加载图片这件事本身是异步的
举个例子,你在html文件中,写如下代码:
![](图片地址1)
此时浏览器就会去请求"图片地址1"这个url中的资源。但只是发送请求而已,什么时候得到结果是不确定的。
如果是是通过js代码,我们会用如下的代码去加载图片:
var img = new Image();
img.src = "图片地址1";
img.onload = function(){
alert("加载成功")
}
img.error = function(){
alert("加载失败")
}
举个实际的应用例子:在网络上加载一张图片后,再用canvas画出来。
下面是错误的代码:
<canvas id="can" width="400" height="400">
</canvas>
<script>
let canvas = document.getElementById('can');
let context = canvas.getContext("2d");
var img = new Image();
img.src="http://img.ivsky.com/img/tupian/pre/201708/18/zhuangguanmeilidetitiantupian.jpg"
context.drawImage(img,0,0) //[2]
</script>
上面的代码错误之处在于,img.src这个属性设置之后,浏览器会去请求这张图,然后接下去执行[2],此时,img并没有请求成功,所以也不会正确地画出图像。
应该要改成:
img.src="http://img.ivsky.com/img/tupian/pre/201708/18/zhuangguanmeilidetitiantupian.jpg";
img.onload = function(){
context.drawImage(img,0,0) //[2]
}
把context.drawImage写在onload事件的回调函数中。意思是:当img加载成功后,才做画图这件事。
下面我们去实现本文开头提出的需求,三张图全部加载成功后,再去做后续的工作。
var img1 = new Image();
var img2 = new Image();
var img3 = new Image();
img1.src = "地址1";
img1.onload = function(){
img2.src = "地址2";
img2.onload = function(){
img3.src = "地址3";
img3.onload = function(){
alert("全部加载完成!")
}
}
}
上面的这一串代码形式有一个专门的名字:callback hell (回调地狱)