zoukankan      html  css  js  c++  java
  • ES6之Promise对象学习——8个例子学会Promise

    目录

    1. Promise 立即执行
    2. Promise 三种状态
    3. Promise 不可逆性
    4. 链式调用
    5. Promise.then()回调异步性
    6. Promise中的异常
    7. Promise.resolve()
    8. resolve vs reject

    一、Promise立即执行

    代码:

    var p = new Promise(function(resolve, reject){
        console.log('create a promise');
        resolve('success');
    });
    
    console.log('after new Promise');
    
    p.then(
        function(val){
            console.log(val);
        },
        function(err){
            console.log(err);
        }
    )

    执行结果:

    *   create a promise
    *   after new Promise
    *   success

    解析:

    Promise对象表示未来要发生的事情,但是在创建 new Promise(function(){}) 时,其中的匿名函数是会被立即执行的,只是其中的代码可以是异步执行的{ example: 体现在 p.then()会被异步执行,但是一定要 这样调用一次resolve(‘success’),才会执行p.then() }。

    二、Promise三种状态

    代码:

    var p1 = new Promise(function(resolve, reject){
        resolve(1);
    });
    
    var p2 = new Promise(function(resolve, reject){
        setTimeout(function(){
            resolve(2);
        }, 500);    
    });
    
    var p3 = new Promise(function(){
        setTimeout(function(){
            resolve(3);
        }, 500);
    });
    
    console.log(p1);
    console.log(p2);
    console.log(p3);
    
    setTimeout(function(){
        console.log(p2);
    }, 1000);
    setTimeout(function(){
        console.log(p3);
    }, 1000);
    
    p1.then(function(val){
        console.log(val);
    });
    p2.then(function(val){
        console.log(val);
    });
    //此处的catch方法,等价于then(fn1, fn2)方法中的fn2。 当resolve()时,执行fn1;当reject时,执行fn2。
    p3.catch(function(err){
        console.log(err);
    });

    执行结果:

    Promise { 1 }
    Promise { <pending> undefined }
    Promise { <pending> undefined }
    1
    2
    3
    Promise { <resolved> 2 }
    Promise { <rejected> 3 }

    解析:

    Promise的内部实现是一个状态机,Promise有3钟状态:pending、resolved、rejected。
    *当Promise刚刚创建完成时,处于pengding。
    *当Promise中的函数执行resolve方法后,由之前的pending –> resolved
    *当Promise中的函数不执行resolve,而是执行了reject方法,那会由之前的pending –> rejected

    三、Promise 状态的不可逆性

    代码:

    var p1 = new Promise(function(resolve, reject){
        resolve('success1');
        resolve('success2');
    });
    
    var p2 = new Promise(function(resolve, reject){
        resolve('success3');
        reject('reject');   
    });
    
    p1.then(function(val){
        console.log(val);
    });
    p2.then(function(val){
        console.log(val);
    });

    执行结果:

    success1
    success

    解析:

    Promise的状态一定确定下来时,Promise的状态和值就固定下来了,不论如何调用 resolve()reject() ,都不能改变它的值和状态。

    四、链式调用

    代码:

    var p = new Promise(function(resolve, reject){
        resolve(1);
    });
    
    p.then(     //第1then
        function(val){
            console.log(val);
            return val*2;
        }
    ).then(     //第2then
        function(val){
            console.log(val);
        }
    ).then(     //第3then
        function(val){
            console.log(val);
            return Promise.resolve('resolve');
        }
    ).then(     //第4then
        function(val){
            cosnole.log(val);
            return Promise.reject('reject');
        }
    ).then(     //第5then
        function(val){
            console.log('resolve=' + val);
        }, function(err){
            console.log('reject=' + err);
        }
    );
    

    执行结果:

    1
    2
    undefined
    resolve
    reject=reject

    解析:

    Promise对象的then方法返回一个新的Promise对象,因此可以通过链式调用then方法。then方法接收2个参数,第一个参数是Promise执行成功时的回调;第二个是Promise执行失败的回调。2个函数只有一个被调用,函数的返回值将被用作创建then返回的Promise对象,这2个参数的返回值可以是一下3种情况中的一种:
    * return 一个同步值 或者 undefined (当没有一个有效的返回值时,默认返回undefined,then方法将返回一个resolved状态的Promise对象,Promise对象的值就是这个返回值。)
    * return 另一个Promise, then方法将根据这个Promise的状态和值创建一个新的Promise对象返回。
    * throw 一个同步异常,then方法将返回一个rejected状态的Promise和该异常值。

    所以 第一个then返回值是:2;第二个then没有返回值,默认返回undefined;第三个then会返回一个状态是resolved值是resolve的新Promise对象;第四个then会返回一个状态为rejected值为reject的新Promise对象;第五个then因为执行失败,会走第二个函数。

    五、Promise.then()回调异步性

    代码:

    var p1 = new Promise(function(resolve, reject){
        resolve('success');
    });
    
    p1.then(function(val){
        console.log(val);
    });
    
    console.log("which one is called first ?");

    执行结果:

    which one is called first ?
    success

    解析:

    Promise接收的函数是同步执行的,但是then中的回调函数的执行则是异步的。

    因此‘sucees’会在后面输出。

    为什么then会优先于定时器先执行?
    *是因为等待队列(或者说是任务队列)其实是分为两个: macrotask 和 microtask;promise是存放在microtasks中,而定时器是存放在macrotasks中,但是在每次”事件循环”后会先执行microtask中的内容,并且当这些 microtask 执行结束后还能继续添加 microtask 一直到真个 microtask 队列执行结束(这也就是所说的”拆箱”),直到当前microtask执行结束之后,才会执行macrotask中的任务,并且往下进行”事件循环”所以才会出现如上代码输出的结果。

    六、Promise中的异常

    代码:

    var p1 = new Promise(function(resolve, reject){
        foo.bar();//异常执行
        resolve(1);
    });
    
    p1.then(
        function(val){
            console.log('p1 then val:' + val);
        }, function(err){
            console.log('p1 then err:' + val);
        }
    ).then(
        function(val){
            console.log('p1 then val:' + val);
        }, function(err){
            console.log('p1 then err:' + val);
        }
    );
    
    var p2 = new Promise(function(resolve, reject){
        resolve(2);
    });
    
    p2.then(
        function(val){
            console.log('p2 then val:' + val);
            foo.bar();//异常执行
        }, function(err){
            console.log('p2 then err:' + val);
        }
    ).then(
        function(val){
            console.log('p2 then val:' + val);
        }, function(err){
            console.log('p2 then err:' + val);
            return 1;
        }
    ).then(
        function(val){
            console.log('p2 then val:' + val);
        }, function(err){
            console.log('p2 then err:' + val);
        }
    );

    执行结果:

    p1 then err: ReferenceError: foo is not defined
    p2 then value: 2
    p1 then value: undefined
    p2 then err: ReferenceError: foo is not defined
    p2 then value: 1

    解析:

    Promise中的异常有then参数中的第二个回调函数 (Promise执行失败的回调) 处理,异常信息作为Promise的值。异常一旦得到处理, then后返回的后续Promise对象恢复正常,并会被Promise执行成功的回调函数处理。 另外需要注意:p1、p2多级then的回调函数是交替执行的,这正是由于Promise then回调的异步性决定的。

    七、Promise中的异常

    代码:

    var p1 = Promise.resolve(1);
    var p2 = Promise.resolve(p1);
    var p3 = new Promise(function(resolve, reject){
        resolve(1);
    });
    var p4 = new Promise(function(resolve, reject){
        resolve(p1);
    });
    
    console.log( p1 === p2 );
    console.log( p1 === p3 );
    console.log( p1 === p4 );
    console.log( p3 === p4 );
    
    p4.then(function(val){
        console.log('p4=' + val);
    });
    
    p2.then(function(val){
        console.log('p2=' + val);
    });
    
    p1.then(function(val){
        console.log('p1=' + val);
    });

    执行结果:

    true
    false
    false
    false
    p2=1
    p1=1
    p4=1

    解析:
    Promise.resolve(…)可以接收一个值或者是一个Promise对象作为参数。
    * 当参数为普通值时,他返回一个resolved状态的Promise对象,对象的值就是这个参数。
    * 当参数为一个Promise对象时,会直接返回这个Promise对象。
    * 使用new创建的Promise对象是一个全新的对象。
    所以p1===p2,所以p1不等于p3,p4。
    p4之所以是最先调用最后输出是因为:
    p4接收的是一个promise对象p1,resolve会对p1进行’拆箱’,获取p1的值。

    八.resolve vs reject

    代码:

    var p1 = new Promise(function(resolve, reject){
        resolve(Promise.resolve('resolve'));
    });
    
    var p2 = new Promise(function(resolve, reject){
        resolve(Promise.reject('reject'));
    });
    
    var p3 = new Promise(function(resolve, reject){
        reject(Promise.resolve('resolve'));
    });
    
    
    p1.then(
            function(val){
                console.log('p3[val]=' + val );
            },
            function(err){
                console.log('p3[err]=' + err ); 
            }
        )
    
    p2.then(
            function(val){
                console.log('p3[val]=' + val );
            },
            function(err){
                console.log('p3[err]=' + err ); 
            }
        )
    
    p3.then(
            function(val){
                console.log('p3[val]=' + val );
            },
            function(err){
                console.log('p3[err]=' + err ); 
            }
        )

    执行结果:

    *   p3[err]=[object Promise]
    *   p3[val]=resolve
    *   p3[err]=reject

    解析:
    * resolve 可以’拆箱’Promise对象; reject不能’拆箱’Promise对象。

    原文地址:https://juejin.im/post/597724c26fb9a06bb75260e8

  • 相关阅读:
    ASP.Net TreeView递归
    WCF发布到IIS7问题的解决方案 (转)
    NavigationService
    【WPF】如何保存RichTextBox的文本到数据库?以及如何对RichTextBox的Document做绑定? Life Is Art 博客园
    Visibility
    WPF操作RichTextBox(转)
    WCF4.0进阶系列第三章 构建健壮的程序和服务(转)
    TreeView(递归)(转)
    WCF4.0 进阶系列–前言(转)
    递归删除树结构数据
  • 原文地址:https://www.cnblogs.com/wenwenwei/p/10017852.html
Copyright © 2011-2022 走看看