再探异步编程之与for循环的调用顺序

需求与研究目的

最近在项目中遇到了这样的问题;进行循环几千次的时候,渲染一个模型;由于模型渲染的比较缓慢,所以模型渲染函数是进行异步调用的;而且是异步里嵌套异步,这就导致了业务流程异常繁琐.所以在这里,想探究总结下前端对异步操作的理解.

什么是异步

我们在日常开发中,常碰到的异步操作如下:
1 ajax服务请求,包括请求什么图片啊,数据啊…
2 常见的一些回调啊,promise类的
理解:
个人对异步的理解还停留在表现;具体的说思维逻辑就是:
在前端开发中,我们的代码都是一行一行的按照顺序往下执行;如果突然,在某处卡死了,造成卡死的原因有很多;那么,我们整个程序就崩了;换句话说,当我们在某处请求个超大资源的时候,比如耗时1分钟,那么这1分钟,我们的程序啥都做不了,造成了资源浪费;这个时候,我们希望,在请求的同时,代码继续向下执行,等请求完了,在对请求的结果进行逻辑处理,所以就产生了异步;

一个异步的情景

这里例句一个例子,在网上,查找了很多异步的例子,但是感觉大都是cp工程师的粘贴复制,很少有自己的见解;所以这里我自己想了一个情景:

A,B两个人,A给了B一百元买一瓶水,这瓶水3元,那么B要找零97元,
找零97元是一个很耗时的过程,毕竟要数钱嘛;在数钱的过程中,A已经很口渴了,
他就直接去拿水了,所以A拿水的结果,是与B是否把钱找零给A没有关系的;这个过程就是一个异步过程;

1 按照正常的逻辑

	function A_给钱(){
        console.log("A给了100元钱给B");
    }
    function A_拿水(){
        console.log("A去拿水喝");
    }
    function B_找零钱(){
        console.log("B找给A 97元");
    }
    A_给钱();
    B_找零钱();
    A_拿水();

在这里插入图片描述2 但是现实中,我们一般等不到A找钱

	function A_给钱(){
        console.log("A给了100元钱给B");
    }
    function A_拿水(){
        console.log("A去拿水喝");
    }
    function B_找零钱(){
        console.log("B找给A 97元");
    }
    A_给钱();
    A_拿水();
    B_找零钱();

在这里插入图片描述
3 在2中的例子,一般是现实情况;但是在仔细想想,一般来说,真正的情景应该是这样的:A先给钱,去拿水,然后B刚好数完钱给A;所以这里有个前置条件,就是A给了钱,才能拿水(不要钻牛角尖,说什么能先拿水在给钱)

function A_给钱(callback){
        console.log("A给了100元钱给B");
        callback();
    }
    function A_拿水(){
        console.log("A去拿水喝");
    }
    function B_找零钱(){        
        console.log("B找给A 97元");
    }
    A_给钱(B_找零钱);
    A_拿水();

在这里插入图片描述
我们看到,利用回调函数,B找钱是需要A给钱这个条件的;我们进一步还原情景,我们知道,找钱是需要时间的
4 根据上述推理,我们在找钱的时候给一个延迟时间

function A_给钱(callback){
        console.log("A给了100元钱给B");
        callback();
    }
    function A_拿水(){
        console.log("A去拿水喝");
    }
    function B_找零钱(){    
        setTimeout(()=>{
            console.log("B找给A 97元");
        },3000)           
    }
    A_给钱(B_找零钱);
    A_拿水();

在这里插入图片描述从上面的例子中,我们能收获些什么呢?
1 settimeout是异步的
2 回调函数通常用来处理异步过程
3 抽象出回调的异步模型(常用语实战中)

	function A(callback){
        //做些什么事情,但是很耗时间
        callback();
    }
    function B(){
        //这里执行的业务逻辑需要A的结果
    }
    A(B)

可能小伙伴只看抽象的还不能很理解,我具象化下:
我们假设,A同学很聪明,B同学很笨;这时,B同学被老师点名算1到10的和,B向A小声求救,A算出来后,告诉了B,B回答了老师的问题

		function A(callback){
        //做些什么事情,但是很耗时间,这里比如我计算1+2+3+....10
        setTimeout(()=>{
            var count=0;
            for(var i=0;i<11;i++){
                count+=i;
            }
            callback(count);
        },5000)
        
    }
    function B(data){
        //这里执行的业务逻辑需要A的结果
        console.log("老师,我算出来了,结果是:",data);
    }
    A(B)
    console.log("C同学在抠脚")

在这里插入图片描述
从结果,你有什么启发呢?C同学在抠脚竟然先执行了;这说明了什么?说明浏览器没有等到A(B)运行完再去往下运行.这就是异步;

带着问题来学习

情景大概是这样的,就是在一个for循环中,循环几百次吧,然后循环的Array对象是后台ajax服务返回的,然后每循环一次,要做很多业务操作,然后在调用一个异步渲染过程;最后渲染的数据总是出错;(关键是错都不报,直接死掉,排查很困难,上千行代码…),所以这里我抽象一个模型出来:

非常经典的模型
 for(var i=0;i<10;i++){

        setTimeout(()=>{
            console.log(i);
        },1000)

}

在这里插入图片描述
不出意外,输出10个10,为什么呢?我想基本人人都懂吧…因为1秒后,循环早就都循环完毕了,最后i等于10;
解决办法:
1 在es6中,我们用let,可以限定作用域,解决(本质原理是什么?我也忘记了…)

for(let i=0;i<10;i++){

        setTimeout(()=>{
            console.log(i);
        },1000)

    }

在这里插入图片描述2 使用变量替代

for(var i=0;i<10;i++){
        let k=i;
        setTimeout(()=>{
            console.log(k);
        },1000)
    }

在这里插入图片描述
差不多解决办法就是这些吧;
当然网上还有一些对函数的异步操作,像什么搞观察者模式啊,promise啊,其实都差不多;当然我脑洞大开,不是有个aysnc await嘛,心想能不能等变异步为同步啊,跟ajax差不多,哈哈;

aynsc await学习

说到aynsc awati,不得不说promise,他们都是为了解决异步编程而提出的概念,可以推荐大家看一篇博文
https://www.cnblogs.com/CandyManPing/p/9384104.html
感觉写的还可以.这里promise就不多说了,主要说下aynsc await
这里有几点需要时刻放在脑子里:
1 aynsc await 的提出是用来解决异步编程的
2 他们是用来异步函数中的,不能随便拿来用
推理过程:
首先,我们有一个异步函数

//这是一个异步函数...应该问题不大
function test() {
        setTimeout(() => {
            return "6";
        }, 3000)
    }

然后我们写个函数对其执行

function test1() {
        let n = test()
        console.log(n)
    }
    test1() //undefined
    这里结果是未定义,不做过多说明,你问我为啥?3秒内test()函数没执行,n肯定是没有值的

那么我们希望n拿到值后再去输出,怎么办?
1 首先我们考虑用promise去解决

function test() {
        return new Promise((rs, rj) => {
            setTimeout(() => {
                rs("6")
            }, 3000)
        })
    }
    function test1() {
        let n = test()
        console.log(n)
        n.then((data) => {
            console.log(data)
        })

    }
    test1()

在这里插入图片描述2 我们在考虑用asyncawait去解决
其实1中的解决例子不是很好,我们更期望加个promise能解决问题,但是我们看到,我们其实也改变了test1中的逻辑
那么我们先来看下async

	async  function test1() {
        return "nihao";    
    }
    let p=test1();
    console.log(p);

在这里插入图片描述其实async返回的是一个promise啊

好了,发现了一个比较通俗易懂的讲解网站,推荐给大家,我就不写了
https://www.cnblogs.com/yuanyingke/p/10280681.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李卓书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值