JS异步变同步
因为Canvas动图绘制需要不定时间消耗,而又不能使用SetTimeout的递归操作,所以不得不将SetTimeout的异步改为同步了。
学习:here
function delate(x) { return new Promise(resolve => { setTimeout(() => { console.log(111); resolve(x); //必须有这一条指令,全靠他 同步了,且将实参原封不动 返回[可无] }, 2000); }); } (async function f1() { for(let j=0;j<10;j++){ var x = await delate(222);// 先 同步调用函数,输出 111 , console.log(x); //等待上一条 同步定时函数 执行结束后,再执行这一条 输出 222 } })()
另外,因为个人使用的操作更为复杂,所以需要进一步学习。
1.如果一个function包含async修饰的子function,而且自身没有使用async+await,那么其子function的执行将会是异步的。
2.async+await修饰的函数,可以递归调用其本身,符合正常逻辑运行。
3.在async表达式修饰的function中,没有await修饰的任意包含SetTimeout异步执行的部分,都会是异步执行。
总结一下,如果只是在一个function中要求其内部异步的SetTimeout同步执行,模板如下:
async function exam() { console.log("步骤1"); // 等待500ms await new Promise(solve => { setTimeout(() => { console.log("步骤2"); solve(); }, 500); }); console.log("步骤3"); }
另外,因为常用的图片资源的onload也是异步,所以写一份学习到的同步onload方法:
var num=0; for (let i=0; i<imgs.length; ++i) { console.log(imgs[i].src); imgs[i].onload=function (i) { console.log("i=="+i+" , 加载图片成功!"); num++; if (num==imgs.length) { console.log("这里执行全部加载完后的操作"); } }(i); }
另外,可能有需要是一个async对应多个await的情况,要使其符合预期运行逻辑顺序,必须要知道其await的执行顺序,学习参考:here
Promise绑定使用后,即顺序执行。
要注意的是,SetTimeout与SetInterval还是有很大区别的,SetInterval只管间隔时间循环执行,不能与async+await套用,
应对的解决办法
1.将SetInterval进行赋值,在时停的地方使用clearInterval(),待时停结束后再赋值SetInterval即可。
但是缺点是应用场景为每一次时停都得从头开始。
2.假性时停,使用帧的计数变量,每一次SetInterval函数体运行一次就+1,那么根据需要的时停时间固定给计数变量进行特判,当变量符合预期范围,才真正运行函数体内容,以实现时停的效果。
-----------------------------------下面这段没用,但是是一个需要解决的问题--------------------------------------------------------
另外,注意到因为这种onload加载方式通常为批量使用,而又存在多个imgs(变量名不同)的情况,所以将其封装成了通用函数:
function Onload_index(x) { for (let i=0; i<x.length; ++i) { x[i].onload=function (x, i) { console.log(x[i].src); console.log("加载完背景图片"+i+"!!!!!!!!!!!!!!!!!!"); }(x, i); } }
还有一点,使用这种通用函数的常识,js的形参和实参,学习:here
copy内容:
形参和实参是存在一种引用关系的,就好比变量中的引用关系。我们都知道,变量中的引用关系跟它们的值有关。
当值为原始类型时(string,number,boolean,int等等),var a=b是各自引用不同的内存地址的,修改不会影响到彼此;
当值是对象,数组等非原始类型时,它们引用的是同一个内存地址,修改则会相互影响。
所以当 函数中的形参是 原始类型,就不会影响到实参的值,因为引用的是值
当函数中的形参是 对象类型,引用的是地址,会影响实参。
-----------------------------------------------------------------------------------------------------------------------------------
使用经验:
使用canvas的drawImage绘制的图片,如果分有多次绘制,那么后续的绘制都是不需要onload处理的,比如有通过onclick事件绑定的绘制,那么该图片就不需要再进行onload处理。
也就是说,只需要onload处理首页显示所涉及到的Image即可。其他,直接draw。
【Over】

浙公网安备 33010602011771号