zoukankan      html  css  js  c++  java
  • js异步处理历程

    为什么会出现异步:

       js执行环境是单线程的,异步处理就非常重要。

    处理的方法:

    方法一:callback hell

    解决:解决了异步处理

    存在问题:出现多个回调函数嵌套,代码就会比较乱,出现回调地狱现象

    方法二:Promise

    解决:Promise的写法只是回调函数的改进,使用then方法,只是让异步任务的两段执行更清楚而已。

    存在问题:Promise的最大问题是代码冗余,请求任务多时,一堆的then,也使得原来的语义变得很不清楚。

    方法三:Generator

    特征:有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态。

    理解:

      调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,必须调用遍历器对象的next方法,使得指针移向下一个状态。

      也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。

      换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行

    解决:Generator函数的机制更符合我们理解的异步编程思想

    存在问题:流程管理却不方便

    方法四:async/await

    解决:ES8引入了async函数,使得异步操作变得更加方便。简单说来,它就是Generator函数的语法糖。

      

    ——————————————————

    需求一:利用上面四种方法完成需求:

      图片一加载完之后加载图片二,
      图片二加载完之后加载图片三,
      图片三加载完之后加载图片四;

    图片地址:

        url1 = 'http://es6.ruanyifeng.com/images/cover_thumbnail_3rd.jpg';
        url2 = 'http://pic22.nipic.com/20120621/1628220_155636709122_2.jpg';
        url3 = 'http://file27.mafengwo.net/M00/5E/6E/wKgB6lPrJiiAFqFIAA1ZCe9u3vo07.jpeg';
        url4 = 'http://img2.imgtn.bdimg.com/it/u=1198844836,3147847928&fm=26&gp=0.jpg';
    View Code

    方法一:callback hell

       function getImage(url,success,fail){
            let img = document.createElement('img');
            img.src = url;
            img.onload = function () {
                success(img);
            }
            img.onerror = function () {
                fail();
            }
        }
        //加载图片一
        getImage(url1,(img)=>{
            console.log('图片一',img.width);
            //加载图片二
            setTimeout(()=>{
                getImage(url2,(img)=>{
                    console.log('图片二',img.width);
                    //加载图片三
                    setTimeout(()=>{
                        getImage(url3,(img)=>{
                            console.log('图片三',img.width);
                            //加载图片四
                            setTimeout(()=>{
                                getImage(url4,(img)=>{
                                    console.log('图片四',img.width);
    
                                })
                            },100)
    
                        })
                    },100)
    
                })
            },100)
    
    
        },()=>{
            console.log('失败')
        })
    View Code

    方法二:Promise

        function getImage(url) {
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = url;
                img.onload = function () {
                    resolve(img);
                }
                img.onerror = function () {
                    reject();
                }
            })
        }
        //方法一:
        getImage(url1).then((img)=>{
            console.log('图片一',img.width);
            setTimeout(()=>{
                getImage(url2).then((img)=>{
                    console.log('图片二',img.width);
    
                    setTimeout(()=>{
                        getImage(url3).then((img)=>{
                            console.log('图片三',img.width);
    
                            setTimeout(()=>{
                                getImage(url4).then((img)=>{
                                    console.log('图片四',img.width);
                                });
                            },100)
                        });
                    },100)
                });
            },100)
    
        }).catch(()=>{
            console.log('失败')
        })
    
        //方法二:
        getImage(url1).then((img)=>{
            console.log('图片一',img.width);
            return getImage(url2)
    
        }).then((img)=>{
            console.log('图片二',img.width)
            return getImage(url3)
        }).then((img)=>{
            console.log('图片三',img.width)
            return getImage(url4)
        }).then((img)=>{
            console.log('图片四',img.width)
        }).catch(()=>{
            console.log('失败')
        })
    View Code

    方法三:Generator

        function getImage(url) {
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = url;
                img.onload = function () {
                    resolve(img);
                }
                img.onerror = function () {
                    reject();
                }
            })
        }
        function * getUrl() {
            yield getImage(url1).then((img)=>{
                console.log('图片一',img.width);
            });
            yield getImage(url2).then((img)=>{
                console.log('图片二',img.width);
            });
            yield getImage(url3).then((img)=>{
                console.log('图片三',img.width);
            });
            return getImage(url4).then((img)=>{
                console.log('图片四',img.width);
            });
        }
    
        var gU = getUrl();
        //存在问题:为什么不是按照顺序打印的?
        gU.next();
        gU.next();
        gU.next();
        gU.next();
    View Code

    方法四:async/await

        function getImage(url) {
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = url;
                img.onload = function () {
                    resolve(img);
                }
                img.onerror = function () {
                    reject();
                }
            })
        }
    
        document.onclick = async function() {
    
            //捕获错误的情况
            try{
                let img1 = await getImage(url1)
                console.log(img1.width);
    
                let img2 = await getImage(url2)
                console.log(img2.width)
    
                let img3 = await getImage(url3)
                console.log(img3.width)
    
                let img4 = await getImage(url4)
                console.log(img4.width)
            }catch (e) {
                console.log('图一加载失败');
            }
        }
    View Code

    ——————————————————

    需求二:利用Promise和async完成需求:

      图片一、二、三加载完之后加载图片四;

    方法一:Promise

        function getImage(url) {
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = url;
                img.onload = function () {
                    resolve(img);
                }
                img.onerror = function () {
                    reject();
                }
            })
        }
        Promise.all([getImage(url1),getImage(url2),getImage(url3)]).then((imgUrl)=>{
            console.log(imgUrl);
            imgUrl.forEach((item)=>{
                console.log(item.width)
            })
            getImage(url4).then((img)=>{
                console.log('图片四',img.width);
            })
        })
    View Code

    方法二:async/await

        function getImage(url) {
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = url;
                img.onload = function () {
                    resolve(img);
                }
                img.onerror = function () {
                    reject();
                }
            })
        }
    
        document.onclick = async function() {
            //捕获错误的情况
            try{
                let imgUrl = await Promise.all([getImage(url1),getImage(url2),getImage(url3)]);
                imgUrl.forEach((item)=>{
                    console.log(item.width)
                })
    
                let img4 = await getImage(url4)
                console.log(img4.width)
            }catch (e) {
                console.log('加载失败');
            }
        }
    View Code

        

    参考文章:

    https://blog.csdn.net/web_csdn_share/article/details/80094779

  • 相关阅读:
    until循环
    linux的shell使用
    shell通配符(元字符)
    linu运算
    mail邮件
    linux命令
    redis笔记
    mysql 5.7安装方法
    mysql5.7.25搭建mysql-5.7.25.tar.gz包(亲验)
    mysql数据迁移
  • 原文地址:https://www.cnblogs.com/shaokevin/p/9796594.html
Copyright © 2011-2022 走看看