为什么会出现异步:

   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

 

posted on 2018-10-16 11:05  阳光毛毛泡泡  阅读(194)  评论(0编辑  收藏  举报