美文网首页
js-Promise基础

js-Promise基础

作者: 发挥不广泛 | 来源:发表于2018-08-10 00:38 被阅读0次

    js-Promise基础(第三周)


    Promise含义

    promise意思为允诺、许诺、承诺
    在js中为了解决编写代码中的地狱回调,而封装的一个类,实现了同步编程风格来实现异步功能,其本质还是各种回调,它先有社区提出和实现,现在ES6也将promise吸进了,提供了原生的Promise了


    Promise简单描述

    promise表示一个异步操作的状态,和返回结果,promise有三种状态分别为pending(进行中)、resolved(已完成,又称fulfilled)、rejected(失败);
    当promise状态由pending转变为resolved或者rejected时,会相应的执行各自的方法,并且状态一点改变,就不会再次改变,这个可能就是Promise(承诺)这个名字的由来;


    生成Promise对象

    一般使用两种方法:

    • 第一,直接new一个promise对象
        let promise = new Promise(function(resolve,reject){
            //异步操作的代码
            if(){       //判断是否成功
                resolve(value)//成功后执行代码,值可以再promise.then(value)取出
            }else{
                reject(err)//捕获错误
            }
        })
    
    
    • 第二,在函数中用return 返回promise对象,可以传参
        function promise(abc){
            return new Promise(function(resolve,reject){
                //异步操作的代码
            if(){       //判断是否成功
                resolve(value)//成功后执行代码,值可以再promise.then(value)取出
            }else{
                reject(err)//捕获错误
            }
            })
        }
    
    
    • promise三种状态
    function promise (abc){
       return new Promise(function(resolve,reject){
       
           if(abc){
               setTimeout(() => {  
               resolve("resolve");     //延时100ms后执行resolve
               }, 100);
               
           }else{
               setTimeout(() => {
               reject("reject");     //延时100ms后执行reject
               }, 100);
           }
    
       })
    }
    let promise1 = promise(true);//能够执行resolve的promise对象
    let promise2 = promise(false);//能够执行reject的promise对象
    console.log(promise1);      // 初始状态promise1
    console.log(promise2);      // 初始状态promise2
    setTimeout(() => {
    console.log(promise1);      //延时200ms后的promise1
    }, 200);
    setTimeout(() => {
    console.log(promise2);      //延时200ms后的promise2
    }, 200);
    
    

    结果:


    image.png

    then()和catch()

    then方法是promise对象的方法,可以分别指定resolved状态和rejected状态的回调函数。then方法可以接收两个回调函数作为参数。以一个参数是promise对象状态为resolved是调用的,第二个参数是promise对象状态为rejected时调用,第二个可数是可以选参数。
    catch方法在作用是捕获Promise的错误,与then方法的rejected回调作用几乎一致,但是由于Promise的抛错具有冒泡性质,能够不断传递,这样就能够在下一个catch()中统一处理这些错误。同时catch()也能够捕获then()中抛出的错误,所以建议不要使用then()的rejected回调,而是统一使用catch()来处理错误

    function promise(abc){
        return new Promise(function(resolve,reject){
            if(abc){
                resolve("这是resolve方法");
            }else{
                throw err= new Error("reject方法执行")//自定义错误
                reject(err)
            }
        })
    }
    promise(true).then(function(data){
        console.log(data);      //输出 这是resolve方法
    },function(err){
        console.log(err);       //不执行
    })
    promise(false).then(function(data){
        console.log(data);      //不执行
    },function(err){
        console.log(err);       //输出 Error:reject方法执行
    })
    promise(true).then(function(data){//建议写法
        console.log(data);       //输出 这是resolve方法
    }).catch(function(err){
        console.log(err);       //不执行
    })
    promise(false).then(function(data){//建议写法
        console.log(data);      //不执行
    }).catch(function(err){
        console.log(err);        //输出 这是resolve方法
    })
    
    

    结果:


    image.png

    使用

    场景回顾看原帖

    我今年18岁,准备找个女朋友,有三个人选(姑娘A、B、C),我表白之后姑娘都会过一段时间给我回复;我最喜欢A姑娘,不过我不知A姑娘是不是也喜欢我,表白成功率为0.4,我次之喜欢B姑娘,表白成功率为0.5,我知道姑娘C很喜欢我,表白成率为1,那么问题来了,谁会成为我最终的女票呢?

    新场景:最终姑娘A答应我的表白请求,准备登记结婚,结婚领证是需要各自的身份证号,才能领取

    场景模拟:用一个数组来收集两个人的身份证号,收集到两个身份证号是将这个数组通过一个方法装换成结婚证
    普通回调:

    let info = []
    function myId(fn){
        fn(1024)
    }
    function amieId(fn){
        fn(1314520)
    }
    function writeId(id,callback){
        info.push(id)
        console.log(info)
        if(callback){
            callback()
        }
    }
    // 开始调用 如果比这再多几层,就不容易看懂了
    myId(function(my_Id){
        console.log(`我的身份证号:${my_Id}`)
        writeId(my_Id, function(){
            amieId(function(amie_Id){
                console.log(`姑娘A的身份证号:${amie_Id}`)
                writeId(amie_Id,function(){
                    console.log(`生成了结婚证,结婚证号为:${info}`)
                });
             
            })
        })
    })
    
    

    promise方式实现:

    let info = []
    function myId(id){
       return new Promise(function(resolve,reject){
           if(id){
               resolve(id);
           }else{
               reject(Error);
           }
       })
       
    }
    function amieId(id){
       return new Promise(function(resolve,reject){
           if(id){
               resolve(id);
           }else{
               reject(Error);
           }
       })
    }
    function writeId(id){
       return new Promise(function(resolve,reject){
           if(id){
               info.push(id);
               console.log(info);
               
               resolve(id);
               return;
           }else{
               reject(Error);
           }
    
       })
    }
    myId(1024).then(function(data){
               console.log(`我的身份证号:${data}`);
              return writeId(data);
               })
             .then(function(){
              return amieId(1314520)
             }
             )
             .then(function(data){
               console.log(`姑娘A的身份证号:${data}`);
              return writeId(data);
               })
             .then(function(){
               console.log(`生成了结婚证,结婚证号为:${info}`)
             })
    

    两种方式结果都是这样的:


    image.png

    两个在机构上显然promise的这种.then().then().then()……
    比会回调function(function(function(){}){}){}……
    便于阅读和管理;
    之所以Promise对象可以实现链式用法,是因为promise.then()会返回一个新的Promise对象,让前一个Promise对象的终值在then方法中生成一个新的Promise对象,以此类推……


    Promise其他方法

    Promise.resolve()和Promise.reject()

    用来将一个现有的对象包装成Promise对象:
    Promise.resolve()包装不同的对象返回的Promise对象会不同:

    let a = Promise.resolve();
    let b = Promise.resolve("常量");
    let c = Promise.resolve({
        name:"发挥不广泛",
        age:18
    })
    let d = Promise.resolve(b);
    let e = Promise.resolve({
        name:"发挥不广泛",
        age:18,
        then:function(resolve,reject){
            console.log(this);
            resolve(this.age);
        }
    });
    console.log(b===d);      //true
    console.log(a);         //不带参数的
    console.log(b);         //带一个常量参数
    console.log(c);         //带一个没有then方法的对象为参数
    console.log(d);         //带一个Promise对象为参数
    console.log(e);         //带一个有then方法的对象为参数
    setTimeout(() => {      //1000ms后看e状态
        console.log(e);
    }, 1000);
    

    结果:


    image.png

    没有参数:resolved状态的Promise对象
    参数是Promise:原样返回
    参数带有then方法:转换为Promise后立即执行then方法
    参数不带then方法、不是对象或没有参数:返回resolved状态的

    Promise.reject()会直接返回rejected状态的Promise

    Promise.all()

    参数为Promise对象数组,如果有不是Promise的对象,将会先通过上面的Promise.resolve()方法转换

    let promise = Promise.all( [p1, p2, p3] )
    promise.then(
        ...
    ).catch(
        ...
    )
    

    当p1、p2、p3的状态都变成resolved时,promise才会变成resolved,并调用then()的已完成回调,但只要有一个变成rejected状态,promise就会立刻变成rejected状态

    Promise.race()

    let promise = Promise.race( [p1, p2, p3] )
    promise.then(
        ...
    ).catch(
        ...
    )
    

    “竞速”方法,参数与Promise.all()相同,不同的是,参数中的p1、p2、p3只要有一个改变状态,promise就会立刻变成相同的状态并执行对于的回调

    Promise.done() 和 Promise. finally()

    Promise.done方法的用法类似 then方法,可以提供resolved和rejected方法,也可以不提供任何参数,它的主要作用是在回调链的尾端捕捉前面没有被 catch方法 捕捉到的错误

    Promise. finally() 接受一个方法作为参数,这个方法不管promise最终的状态是怎样,都一定会被执行,不用他相当于在resolve方法和reject方法中都写一遍

    <完>
    20180810


    发挥不广泛微信公众号

    发挥不广泛

    相关文章

      网友评论

          本文标题:js-Promise基础

          本文链接:https://www.haomeiwen.com/subject/tkphbftx.html