天天看点

ES6--Promise

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES6--Promise</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
    <script>
        /*
            ES6--Promise
        */
        /*
            1.Promise诞生原因
            2.Promise生命周期
            3.Promise基本用法
                3.1 then()函数
                3.2 catch()函数
                3.3 Promise.all()函数
                3.4 Promise.race()函数
                3.5 Promise.resolve()函数
                3.6 Promise.reject()函数
            4.运用
        */

        // 1.Promise诞生原因
            /*
                在promise以前,在处理多个请求且需依赖另一个请求结果时,常用ajax回调实现。
                但是多次回调会形成‘回调地狱’。

                ‘回调地狱’:
                    代码臃肿,可读性茶。
                    代码耦合度高,可维护性差,难以复用。
                    回调函数时匿名函数,不方便调试。
            */
            // $.ajax({
            //     url:"url",
            //     success:function(res){
            //     console.log('ajax结果111',res)
            //         $.ajax({
            //             url:"url",
            //             success:function(res){
            //             console.log('ajax结果2222',res)
            //             $.ajax({
            //                 url:"url",
            //                 success:function(res){
            //                 console.log('ajax结果2222',res)
            //                 $.ajax({
            //                     url:"url",
            //                     success:function(res){
            //                         console.log('ajax结果2222',res)
            //                     }
            //                 })
            //                 }
            //             })
            //             }
            //         })
            //     }
            // })

        // 2.Promise生命周期
            /*
                每一个promise都有3种状态,即pending(进行中)、fulfilled(已成功)和rejected(已失败)。

                promise在创建时处于pending状态,成功时转为fulfilled,失败时转为rejected。

                状态一旦改变就不能在改变,状态改变一次后得到的就是promise的最终状态。
            */

        // 3.Promise基本用法
            /*
                promise本身是一个构造函数,可以通过new操作符生成promise的实例。

                Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve方法和reject方法。
                如果异步操作成功,则用resolve方法将Promise对象的状态变为“成功”(即从pending变为resolved);
                如果异步操作失败,则用reject方法将状态变为“失败”(即从pending变为rejected)。
            */
                var promise = new Promise(function(resolve, reject) {
                    /* 异步操作成功 */
                    if (true){
                        resolve(value);
                    } else {
                        reject(error);
                    }
                });

                promise.then(function(value) {
                    // success
                }, function(value) {
                    // failure
                });

            // 3.1 then()函数
                /* 
                    promise在原型属性上添加了一个then()函数,表示在promise实例状态改变是执行的回调函数。

                    then() 方法返回一个 Promise (en-US)。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

                    注意:如果忽略针对某个状态的回调函数参数,或者提供非函数 (nonfunction) 参数,
                        那么 then 方法将会丢失关于该状态的回调函数信息,但是并不会产生错误。
                        如果调用 then 的 Promise 的状态(fulfillment 或 rejection)发生改变,
                        但是 then 中并没有关于这种状态的回调函数,那么 then 将创建一个没有经过回调函数处理的新 Promise 对象,
                        这个新 Promise 只是简单地接受调用这个 then 的原 Promise 的终态作为它的终态。

                    语法:
                    p.then(onFulfilled[, onRejected]);

                    p.then(value => {
                    // fulfillment
                    }, reason => {
                    // rejection
                    });
                    参数:
                    onFulfilled 可选
                        当 Promise 变成接受状态(fulfilled)时调用的函数。
                        该函数有一个参数,即接受的最终结果(the fulfillment  value)。
                        如果该参数不是函数,则会在内部被替换为 (x) => x,即原样返回 promise 最终结果的函数
                    onRejected 可选
                        当 Promise 变成拒绝状态(rejected)时调用的函数。
                        该函数有一个参数,即拒绝的原因(rejection reason)。  
                        如果该参数不是函数,则会在内部被替换为一个 "Thrower" 函数 (it throws an error it received as argument)。
                */
               const promis=new Promise((resolve,reject)=>{
                   resolve('1');
               })
               //then链式调用
               promis.then((result)=>{
                   console.log(result);//1
                   return 2;
               }).then((result)=>{
                   console.log(result);//2
               })

            // 3.2 catch()函数
               /*
                    虽然then()函数能解决rejected状态的promise的回调函数,但是并不推荐这么做,
                    而是交给catch()函数来处理。

                    catch() 方法返回一个Promise (en-US),并且处理拒绝的情况。
                    它的行为与调用Promise.prototype.then(undefined, onRejected) 相同。
                    (事实上, calling obj.catch(onRejected) 内部calls obj.then(undefined, onRejected)).

                    语法:
                    p.catch(onRejected);

                    p.catch(function(reason) {
                        // 拒绝
                    });

                    参数:
                    onRejected
                        当Promise 被rejected时,被调用的一个Function。 该函数拥有一个参数:
                        reason    rejection 的原因。
                        如果 onRejected 抛出一个错误或返回一个本身失败的 Promise ,  
                        通过 catch() 返回的Promise 被rejected;否则,它将显示为成功(resolved)。 
               */
              const promis1=new Promise((resolve,reject)=>{
                    throw new Error('test');
               });
               promis1.catch((err)=>{
                   console.log(err);//Error: test
               })

            // 3.3 Promise.all()函数
               /*
                    Promise.all() 方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,
                    并且只返回一个Promise实例, 那个输入的所有promise的resolve回调的结果是一个数组。
                    这个Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,
                    或者输入的iterable里没有promise了的时候。它的reject回调执行是,
                    只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。

                    语法:
                    Promise.all(iterable);

                    参数:
                    iterable
                        一个可迭代对象,如 Array 或 String。

                    返回值:
                        如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise。
                        如果传入的参数不包含任何 promise,则返回一个异步完成(asynchronously resolved) Promise。
                        注意:Google Chrome 58 在这种情况下返回一个已完成(already resolved)状态的 Promise。
                        其它情况下返回一个处理中(pending)的Promise。这个返回的 promise 之后会在所有的 promise 都完成或有一个 promise 失败时异步地变为完成或失败。

               */
                var p1 = Promise.resolve(3);
                var p2 = 1337;
                var p3 = new Promise((resolve, reject) => {
                setTimeout(resolve, 100, 'foo');
                });

                Promise.all([p1, p2, p3]).then(values => {
                console.log(values); // [3, 1337, "foo"]
                });
            // 3.4 Promise.race()函数
                /*
                    Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

                    语法:
                    Promise.race(iterable);

                    参数:
                    iterable
                        可迭代对象,类似Array。详见 iterable。

                    返回值:
                        一个待定的 Promise 只要给定的迭代中的一个promise解决或拒绝,
                        就采用第一个promise的值作为它的值,从而异步地解析或拒绝(一旦堆栈为空)。
                */

            // 3.5 Promise.resolve()函数
                /*
                    Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。
                    如果这个值是一个 promise ,那么将返回这个 promise ;
                    如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
                    否则返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。

                    警告:不要在解析为自身的thenable 上调用Promise.resolve。
                    这将导致无限递归,因为它试图展平无限嵌套的promise。

                    语法:
                    Promise.resolve(value);

                    参数:
                    value
                        将被Promise对象解析的参数,也可以是一个Promise对象,或者是一个thenable。

                    返回值:
                    返回一个带着给定值解析过的Promise对象,如果参数本身就是一个Promise对象,则直接返回这个Promise对象。
                */

            // 3.6 Promise.reject()函数
                /*
                    Promise.reject()方法返回一个带有拒绝原因的Promise对象。

                    语法:
                    Promise.reject(reason);

                    参数:
                    reason
                        表示Promise被拒绝的原因。

                    返回值:
                    一个给定原因了的被拒绝的 Promise。
                */

        // 4.运用
            //4.1 同一个Promise中,resolve()函数和reject()函数先后执行
                /*多次执行resolve()函数和reject()函数*/
                const promis2=new Promise((resolve,reject)=>{
                    resolve('success1');
                    reject('err');
                    resolve('success2');
               });
               promis2.then((res)=>{
                   console.log('then:',res);//then: success1
               })
               .catch((err)=>{
                   console.log('catch:',err);
               });
               /*
                结果:只输出then: success1

                总结:
                一个Promis只有一次状态改变,当执行了resolve()函数后,后续的resolve()函数和reject()函数都不会执行,然后直接进入then()。
               */

            //4.2 两种方法处理rejected状态的Promise
               /*
                    rejected状态的Promise有两种处理方法,一种是then()第二参数,一种是catch()函数。
               */
              Promise.resolve()
              .then((res)=>{
                  throw new Error('err');
              },(err)=>{
                  console.log('faill:',e);
              })
              .catch((err)=>{
                  console.log('faill2:',err)//faill2: Error: err
              });
              /*
                结果:只输出faill2: Error: err

                总结:
                虽然这两种方法都能处理Promise状态变为rejected时的回调,但是then()函数的第二个函数却不能捕获第一个函数中抛出的异常,而catch()函数能够。
                这也是推荐使用catch()函数的原因。
               */
    </script>
</body>
</html>