异步专题

时间秒杀一切 提交于 2020-03-03 07:58:15

同步与异步

/* 
    同步异步是什么: 同步和异步是一种消息通知机制
        同步阻塞:
            A调用B,B处理获得结果,才返回A
            A在这个过程中,一直等待B结果,没有拿到结果之前,需要A(调用者)一直等待和确认调用结果是否返回,拿到结果,然后继续再执行下去.
            做一件事,没有拿到结果之前,就一直等待,一直等到有结果了,再去做下面的事.
        异步非阻塞:
            A调用B,无需等待B结果,B通过状态,通知A或回调函数来处理.
            做一件事,不用等待事情的结果,然后就去忙别的了,有了结果,再通过状态来告诉B,或者通过回调函数来处理.
        生活例子
            小明去图书馆借书,和管理员说找那本书,管理员就去一本本查,查完之后才告诉小明,有没有这个书;
            小明A 图书馆管理员B
            查的这个过程需要时间,所以
            同步 -> 在管理员找到或者找不到的过程中,不回去通知小明,需要小明'一直'去问他结果
            异步 -> 在管理员找到之后,就会'通知方式'去告诉小明,所以小明可以继续干别的事,等待通知管理员通知就行;
*/
{
    // 同步:阻塞
    function test(){
        console.log("test...");
    }
    test();
    console.log("end...");
    // 代码执行过程: test... -> end... 因为他们是一步一步向下执行的;
}
{
    // 异步:非阻塞
    // 在JS中非常典型的 异步函数 :定时器
    function test(){
        setTimeout(()=>{
            console.log("test...")
        },1000)
    }
    test();
    console.log("end...");
    // 执行顺序 -> end... test...
}
{
    // 如何让test执行然后再执行end呢?
    // 1.直接把end放到 test中
    // 2.回调 callback;
    function test(cd){
        setTimeout(()=>{
            console.log("test...");
            cd && cd();
        },1000);
    }
    test(function(){
        console.log("end...");
    });
    // 执行顺序 -> test... end...
}

异步小案例:方块运动

递归

{
    function move(ele, direction, target) {//元素,方向(left,top),目标点
        let start = parseInt(window.getComputedStyle(ele, null)[direction]);//(元素,伪类)[样式名]; -> 获取元素当前位置[有单位];
        let speed = 5;//速度;

        start = start + speed;
        ele.style[direction] = start + "px";
        // 不听的加 -> 递归(调用自身)
        setTimeout(() => {
            if (start === target) {
                console.log("停")
            } else {
                move(ele, direction, target);
            }
        }, 50);
    }
    move(box, 'left', 200)
}

动画帧 requestAnimationFrame

{
    // 动画帧,相对于 setTimeout 性能好一点;
    function move(ele, direction, target) {
        function fn() {
            let start = parseInt(window.getComputedStyle(ele, null)[direction]);
            let speed = 5;

            start = start + speed;
            ele.style[direction] = start + "px";

            if (start == target) {
                console.log("停");
            } else {
                window.requestAnimationFrame(fn);
            }
        }
        fn();
    }
    move(box, 'left', 200)
}

回调

{
    // 如何从上面移动到下边呢 -> 回调 -> 也是回调地域
    function move(ele, direction, target,cd) {
        function fn() {
            let start = parseInt(window.getComputedStyle(ele, null)[direction]);
            let dir = (target-start)/Math.abs(target-start);//判断 正负:(目标点-当前位置)除 Math.abs(目标点-当前位置) -> 1 / -1
            // console.log( 10/Math.abs(10) );//1;
            // console.log( -10/Math.abs(-10) );//0-1;
            let speed = 5 * dir;//* 正得正 负得负

            start = start + speed;
            ele.style[direction] = start + "px";

            if (start == target) {
                console.log("停");
                cd && cd();
            } else {
                window.requestAnimationFrame(fn);
            }
        }
        fn();
    }
    move(box,'left',200,function(){
        move(box,'top',200,function(){
            move(box,'left',0,function(){
                move(box,'top',0);
            })
        })
    });
}

使用promise对象

{
    // promise
    function move(ele, direction, target) {
        return new Promise(resolve => {
            function fn() {
                let start = parseInt(window.getComputedStyle(ele, null)[direction]);
                let dir = (target - start) / Math.abs(target - start);
                let speed = 5 * dir;//* 正得正 负得负

                start = start + speed;
                ele.style[direction] = start + "px";

                if (start == target) {
                    // console.log("停");
                    resolve("停");
                } else {
                    window.requestAnimationFrame(fn);
                }
            }
            fn();
        });
    }
    move(box,'left',200).then(res=>{
        return move(box,'top',200);
    }).then(res=>{
        return move(box,'left',0);
    }).then(res=>{
        return move(box,'top',0);
    }).then(res=>{
        console.log(res);
    })
}

使用async和await

{
    // async和await
    function move(ele, direction, target) {
        return new Promise(resolve => {
            function fn() {
                let start = parseInt(window.getComputedStyle(ele, null)[direction]);
                let dir = (target - start) / Math.abs(target - start);
                let speed = 5 * dir;//* 正得正 负得负

                start = start + speed;
                ele.style[direction] = start + "px";

                if (start == target) {
                    // console.log("停");
                    resolve("停");
                } else {
                    window.requestAnimationFrame(fn);
                }
            }
            fn();
        });
    }
    async function queue() {
        try {
            await move(box, 'left', 200);
            await move(box, 'top', 200);
            await move(box, 'left', 0);
            await move(box, 'top', 0);
            console.log("全部执行完毕");
        } catch (err) {
            // 接收错误;
            console.log(err);
        }
    }
    queue();
}

requestAnimationFrame 与 setTimerout性能比拼

{
    function fn(){
        document.title ++;
        setTimeout(()=>{
            fn();
        },1000);
    }
    // fn();
}
{
    function fn(){
        document.title ++;
        window.requestAnimationFrame(fn);//跳到别的浏览器就 停止了.
    }
    fn();
}

promise对象

{
    /* 
        Promise对象 是一个已经定义好的类;
            三种状态:pending、resolve、reject
    */
    let p1 = new Promise((resolve,reject)=>{
        // 什么都不写 返回 -> pending value="undefined"
        // resolve(111);//resolve value="111" -> 在火狐中也叫:fulfilled 成功
        // reject("error");//失败->报错

        setTimeout(()=>{
            resolve("成功了");
            // reject("错误了");
        },1000);
    });
    // console.log(p1);

    // then -> 就是resolve成功
    // then 两个参数; onresolve、onreject
    /* p1.then((res)=>{
        console.log(res);
    },(error)=>{
        console.log(error);
    }); */
    /* p1.then((res)=>{
        console.log(res);
    }).catch(err=>{//也是错误方法的一种方式
        console.log(err);
    }) */

    // then:三种返还;
    {
        // 1.回调里面没有返还 : 自动返还promise对象;
        /* let reslut = p1.then((res)=>{
            console.log(res);
        });
        console.log(reslut); */

        // 2.回调有返还: 会自动通过promise包装返还值,然后返还promise对象;
        /* let reslut1 = p1.then((res)=>{
            console.log(res);
            return "some value";
        });
        // 所以这里还可以继续 then;
        reslut1.then((res)=>{
            console.log(res);//some value;
        })
        console.log(reslut1); */

        // 3.返还一个promise对象: then就会返还这个promise;
        let reslut2 = p1.then((res)=>{
            return new Promise((resolve)=>{
                resolve("返还的promise");
            });
        });
        console.log(reslut2);
    }
}

promise 加载图片小案例

{
    function loadImg() {
        return new Promise((resolve, reject) => {
            let img = new Image();
            img.src = "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=102864642,3880374403&fm=11&gp=0.jpg";
            img.onload = function () {
                // console.log("加载完成");
                resolve("图片加载完成");
                document.querySelector("body").appendChild(img);
            }
            img.onerror = function(){
                reject("图片加载失败");
            }
        });
    }
    loadImg().then(res=>{
        console.log(res);
    },err=>{
        console.log(err);
    });
}

 async和await

// ES7语法: async 和 await;
{
    let p1 = new Promise(resolve => {
        setTimeout(() => {
            resolve("执行成功")
        }, 1000)
    })
    let p2 = new Promise(resolve => {
        setTimeout(function () {
            resolve("执行成功222")
        }, 2000)
    });
    // 执行完p1然后执行p2
    {
        // p1.then(res => {
        //     console.log(res);
        //     return p2;
        // }).then(res => {
        //     console.log(res);
        //     console.log("都执行完毕");
        // });
    }

    {
        // 异步函数用成了 同步写法
        /* 
            1.async 和 await 要一起出现
            2.await 一定要是一个promise对象;
        */
        async function fn() {
            let res1 = await p1;
            console.log(res1);
            let res2 = await p2;
            console.log(res2);
            console.log("都执行完毕")
        }
        fn();
    }
}

 Promise函数

{
    // Promise是一个对象 resolve是它的静态方法
    // let res = Promise.resolve();
    // console.log(res);//能拿到 promise的resolve
    // let res1 = Promise.reject();
    // console.log(res1);//reject状态的promise对象;

    let p1 = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log(111);
            resolve(111);
        },2000);
    });
    let p2 = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log(222);
            resolve(222);
            // reject("error");
        },1000);
    });
    let p3 = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log(333);
            resolve(333);
        },3000);
    });
    // 前提:所有的promise都要成功;
    // all 把成功结果放到数组中;
    // Promise.all([p1,p2,p3]).then(res=>{
    //     console.log(res);
    // });

    // 拿到执行最快的那个
    Promise.race([p1,p2,p3]).then(res=>{
        console.log(res);
    });
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!