JavaScript第二十章 Promise

Promise

  • Promise 是 ES6 提供的类,是异步编程的一种解决方案,不是指将异步转换为同步的方法,目的是更加优雅地书写复杂的异步任务

优点

1. 对象状态不受外界影响

  • 三个状态
    pending:进行中
    fulfilled:已成功
    reject:已失败
    Promise即承诺的意思,承诺什么呢?即只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态

2. 一旦改变状态,就不会再变,并且任何时候都可以得到这个结果

  • Promise状态的改变只有两种情况:pending到fulfilled与pending到reject
  • 只要这两种情况发生,状态就不会再变了,会一直保持这个结果,这时就称为resolved(已定型),并且可以通过对Promise对象添加回调函数得到这个结果(与事件不同,事件错过再去监听是得不到任何结果的)

缺点

1. 无法取消Promise

  • 一旦新建它就要立即执行,无法中途取消

2. 错误判别

  • 如果不设置回调函数,Promise内部抛出的错误,不会反映到外部

3. 不可预知状态

  • 当处于pending状态时,无法得知目前进展到哪一个状态,是刚刚开始还是即将完成

一、构造 Promise

  • 语法
new Promise(function (resolve, reject) {
    
    
    // to do...
});
  • Promise 构造函数只有一个参数,是一个函数,这个函数在构造之后会直接被异步运行,所以我们称之为起始函数,起始函数包含两个参数 resolve 和 reject,当 Promise 被构造时,起始函数会被异步执行
  • resolve 和 reject 都是函数(JavaScript引擎提供的,不用自己部署),其中调用 resolve 代表一切正常,即在异步函数操作成功的时候调用,并将异步操作的结果作为参数传递出去,reject 是出现异常时所调用的,即在异步操作失败的时候调用,并将异步操作报出的错误作为参数传递出去
  • resolve() 中可以放置一个参数用于向下一个 then 传递一个值,then 中的函数也可以返回一个值传递给 then,但是,如果 then 中返回的是一个 Promise 对象,那么下一个 then 将相当于对这个返回的 Promise 进行操作
  • reject() 参数中一般会传递一个异常给之后的 catch 函数用于处理异常
  • resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列
  • resolve 和 reject 并不能够使起始函数停止运行,应该使用 return

二、Promise 方法

1. then()

  • then() 可以将参数中的函数添加到当前 Promise 的正常执行序列
  • then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列
  • 如何中断then 块:then 块默认会向下顺序执行,return 是不能中断的,可以通过 throw 来跳转至 catch 实现中断
  • then 块可以多次使用,但是 catch 块只会执行第一个,除非 catch 块里有异常,所以最好只安排一个 catch 和 finally 块
  • 当我们需要调用一个异步任务的时候,需要再写一个 then 而不是在当前的 then 接着编程

2. catch()

  • catch() 则是设定 Promise 的异常处理序列

3. finally()

  • finally() 是在 Promise 执行的最后一定会执行的序列
  • then、catch 和 finally 序列可以颠倒顺序,但不建议这样做,最好按 then-catch-finally 的顺序编写程序

三、函数瀑布

  • 用 “函数瀑布” 实现的程序无论是维护还是异常处理都是一件特别繁琐的事情,而且会让缩进格式变得非常冗余
  • 举例
setTimeout(function () {
    
    
    console.log("l");
    setTimeout(function () {
    
    
        console.log("z");
        setTimeout(function () {
    
    
            console.log("j");
        }, 3000);
    }, 2000);
}, 1000);

四、使用Promise改进

  • 有了Promise对象,我们就可以将异步操作以同步操作的流程表达出来,从而避免层层嵌套的回调函数,此外,Promise对象提供统一的接口,使得控制异步操作更加容易
  • 初步改进
new Promise(function (resolve, reject) {
    
    
    setTimeout(function () {
    
    
        console.log("l");
        resolve();
    }, 1000);
}).then(function () {
    
    
    return new Promise(function (resolve, reject) {
    
    
        setTimeout(function () {
    
    
            console.log("z");
            resolve();
        }, 2000);
    });
}).then(function () {
    
    
    setTimeout(function () {
    
    
        console.log("j");
    }, 3000);
});
  • 最终改进
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>promiseTest</title>
    <script>
        /*冗余*/
        // setTimeout(function () {
    
    
        //     console.log("m");
        //     setTimeout(function () {
    
    
        //         console.log("a");
        //         setTimeout(function () {
    
    
        //             console.log("y");
        //         },3000)
        //     },2000)
        // },1000)

        /*初步改进*/
        // resolve 代表一切正常,reject 是出现异常时所调用的
        // new Promise(function (resolve, reject) {
    
    
        //     setTimeout(function () {
    
    
        //         console.log("m");
        //         resolve();
        //     }, 1000);
        // }).then(function () {
    
    
        //     return new Promise(function (resolve, reject) {
    
    
        //         setTimeout(function () {
    
    
        //             console.log("a");
        //             resolve();
        //         }, 2000);
        //     });
        // }).then(function () {
    
    
        //     setTimeout(function () {
    
    
        //         console.log("y");
        //     }, 3000);
        // });

        /*最终优化*/
        // 使用 Promise 函数
        function print(delay, message) {
    
    
            // must write return(to return Promise object)
          return new Promise(function (resolve, reject) {
    
    
                setTimeout(function () {
    
    
                    console.log(message);
                    resolve();
                }, delay);
            });
        }
		
		// 实例
        print(1000,"m").then(function (){
    
    
            return print(2000,"a");
        }).then(function () {
    
    
            print(3000,"y"); // 对上面返回的Promise对象进行操作
        })

    </script>
</head>
<body>
    
</body>
</html>

五、异步函数(async function)

  • 异步函数是通过事件循环(event loop) 异步执行的函数,返回一个隐式的 Promise 作为其结果
  • 语法
async function name([param[, param[, ... param]]]) {
    
     statements }

1. 使用异步函数优化实例

async function asyncFunc() {
    
    
    await print(1000, "m");
    await print(4000, "a");
    await print(3000, "y");
}
asyncFunc();
  • 异步函数 async function 中可以使用 await 指令,await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行,即await 指令暂停异步函数的执行,并等待 Promise的执行结果返回,结果返回后就恢复异步函数的执行,并且await 指令只在异步函数(async functions)内有效,如果在异步函数外使用它,会抛出语法错误

2. try-catch 块处理异常

  • 返回一个promise对象,并返回异步函数的值(如果异步函数是resolve则返回resolve的值;如果抛出异常,则抛出reject在异步函数中声明的异常)
async function testA(){
    
    
    try {
    
    
        await new Promise(function (resolve, reject) {
    
    
            reject("may");
        })
    } catch (e) {
    
    
        console.log(e);
    }
}
testA();

// 返回正常值
async function test(){
    
    
    let t = await new Promise(function (resolve, reject) {
    
    
        resolve("day");
    })
    console.log(t);
}
test();

猜你喜欢

转载自blog.csdn.net/LvJzzZ/article/details/109264225