欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES6高级1:异步promise/async/await

程序员文章站 2023-12-26 21:02:21
...

什么是同步与异步

同步和异步是一种消息通知机制

  1. 同步阻塞
  2. 异步非阻塞

回调地域

ES5的回调就是在一个事件结束之后调用另一个事件

举例:小球四个方向的运动

如果一层嵌套一层一个个回调的话,回调数量一朵,就会非常难看,难以维护

move(ele, "left", 400, function () {
    console.log("向右运动完成");
    move(ele, "top", 400, function () {
        console.log("向下运动完成!")
        move(ele, "left", 0, function () {
            console.log("向左运动完成");
            move(ele, "top", 0, function () {
                alert("运动完成");
            })
        })
    });
});

所以es6就新增了promise方法实现

promise

  • ES6的Promise对象是一个构造函数,用来生成Promise实例。
  • 所谓Promise对象,就是代表了未来某个将要发生的事件(通常是一个异步操作)。
  • 它的好处在于,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

两个参数、三种状态

  • pending 等待中
    ES6高级1:异步promise/async/await
  • fulfilled / resolve 已成功
    ES6高级1:异步promise/async/await
  • reject 已失败:会抛出promise里面的错误
    ES6高级1:异步promise/async/await

then 的两个参数

  1. resolve
  2. reject
    对应promise里的两个参数
let p1 = new Promise((resolve, reject) => {
  resolve("已完成")
//  reject("抛出错误")
})

p1.then(res => {
  console.log(res)
}, err => {
  console.log(err)
})

ES6高级1:异步promise/async/await

then 的三种返回值

1 没有返回值

会拿到和之前状态一样的promise对象

    let p1 = new Promise((resolve, reject) => {
        resolve("已完成")
        //   reject("抛出错误")
    })

    let result = p1.then(res => {
        console.log(res)
    })

    console.log(result)

ES6高级1:异步promise/async/await

2 有返回值

返回的就是promise对象

    let result = p1.then(res => {
        console.log(res)
        return "values"
    })

    console.log(result)

ES6高级1:异步promise/async/await

3 直接返回 new promise对象

    let result = p1.then(res => {
        console.log(res)
        return new Promise((resolve, reject) => {
            resolve("已完成2");
        })
    })

ES6高级1:异步promise/async/await

链式操作

    p1.then(res => {
        console.log(res)
        return new Promise((res => {
            res("已完成2")
        }))
    }).then(res => {
        console.log(res)
        return new Promise((res, reject) => {
            reject("抛出错误")
        })
    }).catch(err => {
        console.log(err)
    })

ES6高级1:异步promise/async/await

Promise的静态方法

    let p1 = new Promise((res,reject)=>{
        setTimeout(()=>{
            res(1);
        },2000)
    })

    let p2 = new Promise((res, reject) => {
        setTimeout(()=> {
            res(2)
        }, 1000)
    })
    let p3 = new Promise((res, reject) => {
        setTimeout(()=> {
            res(3)
        }, 3000)
    })

1 Promise.all 等待所有结果

    Promise.all([p1, p2, p3]).then(res => {
        console.log(res);
    })

ES6高级1:异步promise/async/await

2 .race 只拿到执行最快的结果

    Promise.race([p1, p2, p3]).then(res => {
        console.log(res);
    })

3 直接执行结果或者异常

    let p4 = Promise.resolve("完成");
    let p5 = Promise.reject("抛出异常")
    console.log(p4, p5)

ES6高级1:异步promise/async/await

async await

其实promise并不是最好的解决回调地域的方法
因为promise仍有很多缺点

  1. 无法取消Promise,一旦新建它就会立即执行
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
  3. 当处于pending状态时,无法得知目前进展到哪一个阶段

于是es7又有一个新的特性:async与await,与promise配合使用,将Promise变为同步的写法

用法

用async声明一个函数,在这个函数里面使用await 跟一个Promise对象
这样会使Promise对象从上往下按顺序同步执行

    async function asyncFn() {
        let res = await new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log(111);
                resolve("value1");
            }, 2000)
        })
        console.log(res);

        let res2 = await new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log(222);
                resolve("value2");
            }, 1000)
        })
        console.log(res2);
    }

    asyncFn();

ES6高级1:异步promise/async/await

捕获异常

想从外部捕获Promise内的异常需要try{}catch{}
捕获到错误之后就会终止函数

    async function asyncFn() {
        try {
            let res3 = await new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log(333);
                    reject("错误");
                }, 1000)
            })
            console.log(res3);
            let res5 = await new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log(444);
                    resolve("完成")
                }, 500)
            })
            console.log(res5);
        } catch (e) {
            console.log("error: ", e)
        }
    }

    asyncFn();

使用Promise实现小球运动

    function move(ele, direction, target, cb) {
        return new Promise((resolve, reject) => {
            let start = parseInt(window.getComputedStyle(ele, null)[direction]);
            let speed = (target - start) / Math.abs(target - start) * 5;
            console.log(speed)
            function fn() {
                // 向右 加  向左 减
                start += speed;
                ele.style[direction] = start + "px";
                if (start === target) {
                    resolve("运动完成");
                } else {
                    window.requestAnimationFrame(fn)
                }
            }
            fn();
        })
    }
    let ele = document.querySelector(".box");
    move(ele, "left", 400).then(res => {
        return move(ele, "top", 400);
    }).then(res => {
        return move(ele, "left", 0);
    }).then(res => {
        return move(ele, "top", 0);
    }).then(res => {
        console.log(res)
    }).catch(err => {
        console.log(err)
    })

使用async await改写小球运动

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            left: 0px;
            top: 0px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
</body>
<script>

    function move(ele, direction, target, cb) {
        return new Promise((resolve, reject) => {
            let start = parseInt(window.getComputedStyle(ele, null)[direction]);
            let speed = (target - start) / Math.abs(target - start) * 5;
            console.log(speed)
            function fn() {
                // 向右 加  向左 减
                start += speed;
                ele.style[direction] = start + "px";
                if (start === target) {
                    resolve("运动完成");
                } else {
                    window.requestAnimationFrame(fn)
                }
            }
            fn();
        })
    }
    let ele = document.querySelector(".box");

    async function asyFunc() {
        try {
            let m1 = await move(ele, "left", 400)
            console.log("向右", m1)
            let m2 = await move(ele, "top", 400);
            console.log("向下", m1)
            let m3 = await move(ele, "left", 0);
            console.log("向左", m1)
            let m4 = await move(ele, "top", 0);
            console.log("向上", m1)
        } catch (e) {
            console.log(e)
        }
    }
    asyFunc();

</script>

</html>
相关标签: JavaScript高级

上一篇:

下一篇: