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 @   Renhr  阅读(4488)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示