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
    }
})()
copy来的模板代码

另外,因为个人使用的操作更为复杂,所以需要进一步学习。

  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);
    }
function内部

  

另外,可能有需要是一个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);
    }
}
传入需要onload的imgs数组变量名即可

 

还有一点,使用这种通用函数的常识,js的形参和实参,学习:here

   copy内容:

  形参和实参是存在一种引用关系的,就好比变量中的引用关系。我们都知道,变量中的引用关系跟它们的值有关。

  当值为原始类型时(string,number,boolean,int等等),var a=b是各自引用不同的内存地址的,修改不会影响到彼此;

  当值是对象,数组等非原始类型时,它们引用的是同一个内存地址,修改则会相互影响。

  所以当 函数中的形参是 原始类型,就不会影响到实参的值,因为引用的是值

  当函数中的形参是 对象类型,引用的是地址,会影响实参。

-----------------------------------------------------------------------------------------------------------------------------------

使用经验:

  使用canvas的drawImage绘制的图片,如果分有多次绘制,那么后续的绘制都是不需要onload处理的,比如有通过onclick事件绑定的绘制,那么该图片就不需要再进行onload处理。

  也就是说,只需要onload处理首页显示所涉及到的Image即可。其他,直接draw。

【Over】

posted @ 2022-08-18 16:39  Renhr  阅读(4586)  评论(0)    收藏  举报