zoukankan      html  css  js  c++  java
  • ES6

    1.Promise介绍

    Promise最早是社区提出和实现,后面ES6将其写入标准,并原生提供Promise对象,是一种异步编程的解决方案,具体的概念大家可以去查看相关的资料。传统上处理异步都是以callback回调函数的方式完成,但是当回调嵌套的太多,便会使程序很难理解,如下所示

    function a(cb){
        console.log('a...');
        cb('a');
    }
    function b(cb){
        console.log('b...');
        cb('b');
    }
    function c(cb){
        console.log('c...');
        cb('c');
    }
    a(() => b( () => c( () => {}) ));
    a...
    b...
    c...

    如果后面还有基于C函数的输出结果的逻辑,回调将是很大的困恼。

    而使用Promise来处理这种异步回调将会非常的直观,Promise以同步的操作完成异步的处理,如下所示

    function a(){
        console.log('a...');
        return 'a output';
    }
    function b(res){
        console.log('b...');
        console.log('get A:'+res);
            return "b output";
    }
    function c(res){
        console.log('c...');
        console.log('get B:'+res);
    }
    new Promise((resolve,reject) => {setTimeout(resolve,1000)}).then(a).then(b).then(c);
    Promise { <state>: "pending" }
    a...
    b...
    get A:a output
    c...
    get B:b output

    2.Promise的用法

    Promise是一个构造函数,接收一个函数参数,该函数接收两个函数作为参数,分别是resolve,reject。这两个函数由Promise自己提供,无需自己部署。resolve函数将Promise的状态从'Pending'转为'Resolved',reject函数将状态从'Pending'转为'rejected'。

    基本语法,如下所示

    new Promise((resolve,reject) => {
        if(success){ //异步处理成功
            resolve();
        }else{
            reject();
        }
    }).then(onFulfilled,onRejected);

    创建一个Promise实例,如下所示

    var promise = new Promise((resolve,reject) => {console.log('hehe');resolve('resolved')});
    promise.then((val) => console.log(val))
    console.log('current');
    hehe
    current
    resolved

    resolve函数与reject函数调用时可以传递参数,一般给reject函数传递Error的实例,用于指出抛出的错误,传给reject函数的参数可以是一般的数值,也可以是Promise的实例,这时该Promise的实例状态由参数Promise实例的状态决定,如下所示

    var p1 = new Promise((resolve,reject) => {
        setTimeout(()=>{console.log('1秒后的 p1');resolve(p2);},1000);
    });
    var p2 = new Promise((resolve,reject)=>{
        setTimeout(()=>{console.log('2秒后的 p2');resolve('p2');},2000);
    });
    
    p1.then((val)=>console.log(val));
    Promise { <state>: "pending" }
    1秒后的 p1
    2秒后的 p2
    p2

    如上所示,Promise是创建就立即执行,且then方法的回调函数将在当前脚本所有同步语句执行完执行,但是比定时器的队列优先级要高,如下所示

    setTimeout(()=>console.log('settimeouting...'),0);
    var promise = new Promise((resolve,reject) => {
        console.log('promise constructing...');
        reject(new Error('error'));
    });
    promise.then(null,(reason)=>console.log(reason));
    promise constructing...
    Promise { <state>: "pending" }
    Error: error
    堆栈跟踪:
    promise<@debugger eval code:4:9
    @debugger eval code:2:15
    
    settimeouting...

    Promise的原型方法then,该方法为promise实例添加状态改变时的回调函数,第一个参数是状态为resolved时的回调,第二个参数是状态为rejected的回调。如下所示

    var p3 = new Promise((resolve,reject) => {
        console.log('p3');
        resolve('p3');
    });
    var p4 = new Promise((resolve,reject) => {
        console.log('p4');
        setTimeout(()=>resolve('p4'),1500);
    });
    p3.then(()=>p4).then((result) => console.log(result));//这里需要注意一点,如果then方法返回一个Promise实例,则下一个then回调需要等待该Promise实例的状态改变才会执行。
    p3
    p4
    Promise { <state>: "pending" }
    p4

    Promise内部抛出的错误不会被捕获(Chrome浏览器除外),除非使用catch方法,如果在resolve之前抛出,则resolve不会执行,相反则相当于没有抛出错误,如下所示

    var promise = new Promise((resolve,reject) => {
        console.log('promise constructing...');
        throw new Error('error');
        resolve('haha');
    });
    promise.then((val)=>console.log(val));
    promise constructing...
    -------------------------------------------------------------
    var promise = new Promise((resolve,reject) => {
        console.log('promise constructing...');
            resolve('haha');
        throw new Error('error');
        
    });
    promise.then((val)=>console.log(val));
    promise constructing...
    haha

    使用Promise的原型方法catch捕获错误,该方法其实是.then(null,reject)的别名,如下所示

    var promise = new Promise((resolve,reject) => {
        console.log('promise constructing...');
        throw new Error('error');
        resolve('haha');
    });
    promise.then((val)=>console.log(val)).catch((error)=>console.log(error));
    
    promise constructing...
    Promise { <state>: "pending" }
    Error: error
    堆栈跟踪:
    promise<@debugger eval code:3:8
    @debugger eval code:1:19

     Promise的错误捕获可以使用then方法的第二个参数指定reject的回调函数,也可以使用Promise.prototype.catch方法捕获,但是一般推荐使用方法二,因为catch不仅能捕获到promise内部抛出的错误,then方法中的错误也能被捕获。但是在调用resolve方法之后,再抛出错误,不会被捕获,相当于没有抛出错误,如下所示

    var promise = new Promise((resolve,reject) => {
        throw new Error('promise error');
    });
    promise.then(null,(err)=>console.log(err));
    Promise { <state>: "pending" }
    Error: promise error
    堆栈跟踪:
    promise<@debugger eval code:2:9
    @debugger eval code:1:19
    ---------------------------catch method-------------------
    var promise = new Promise((resolve,reject) => {
        reject(new Error('promise error'));
    });
    promise.catch((error)=>console.log(error));
    Promise { <state>: "pending" }
    Error: promise error
    堆栈跟踪:
    promise<@debugger eval code:2:9
    @debugger eval code:1:19
    ---------------------------then方法中报错-------------------
    var p5 = new Promise((resolve,reject) => {
        resolve('hehe');
    });
    p5.then((val)=>val+x).catch((err)=>console.log(err));
    Promise { <state>: "pending" }
    ReferenceError: x is not defined
    堆栈跟踪:
    @debugger eval code:4:16

    catch方法也是返回一个Promise,因此在catch后面还可以接着使用链式方法then,但这时then方法报错将不会被前面的catch捕获,如下所示

    var p5 = new Promise((resolve,reject) => {
        resolve('hehe');
    });
    p5.then((val)=>val+x).catch((err)=>console.log(err)).then((val)=>y+3);
    Promise { <state>: "pending" }
    ReferenceError: x is not defined
    堆栈跟踪:
    @debugger eval code:4:16

    3.Promise.all

    Promise.all方法可以将多个Promise实例[p1,p2,p3...]包装成一个Promise对象A,A的状态由p1,p2,p3...决定:如果p1,p2,p3...的状态都变为onfulfilled,A的状态才变为onfulfilled,且p1,p2,p3...的异步操作结果组成一个数组传给回调函数;但凡p1,p2,p3...中有一个状态变为了rejected,A的状态立即变为rejected,且第一个rejected的返回值会传给回调函数,如下所示

    var p1 = new Promise((resolve,reject) => {
        console.log('p1...');
        setTimeout(()=>resolve('p1 resolved...'),1000);
    });
    var p2 = new Promise((resolve,reject) => {
        console.log('p2...');
        setTimeout(()=>resolve('p2 resolved...'),2000);
    });
    var p3 = new Promise((resolve,reject) => {
        console.log('p3...');
        setTimeout(()=>resolve('p3 resolved...'),3000);
    });
    
    Promise.all([p1,p2,p3]).then((args)=>{console.log('3S后的输出:');for(let v of args){console.log(v);}});
    p1...
    p2...
    p3...
    3S后的输出:
    p1 resolved...
    p2 resolved...
    p3 resolved...
    ------------------------  有一个Promise实例变为rejected ---------------
    var p1 = new Promise((resolve,reject) => {
        console.log('p1...');
        setTimeout(()=>resolve('p1 resolved...'),1000);
    });
    var p2 = new Promise((resolve,reject) => {
        console.log('p2...');
        setTimeout(()=>resolve('p2 resolved...'),2000);
    });
    var p3 = new Promise((resolve,reject) => {
        console.log('p3...');
        setTimeout(()=>resolve('p3 resolved...'),3000);
    });
    var p4 = new Promise((resolve,reject) => {
        console.log('p4...');
        reject("p4 rejected...");
    });
    Promise.all([p1,p2,p3,p4]).then((args)=>console.log(args),(reason) => console.log(reason));
    p1...
    p2...
    p3...
    p4...
    Promise { <state>: "pending" }
    p4 rejected...

    4.Promise.race

    同Promise.all一样,该方法也是将多个Promise实例[p1,p2,p3...]包装成一个新的Promise实例B。"race"的字面意思就是竞争,所以[p1,p2,p3...]谁的状态先改变,B的状态立即改变一样的状态且第一个改变状态的promise实例的返回值传递给回调函数,如下所示

    var p1 = new Promise((resolve,reject) => {
        console.log('p1...');
        setTimeout(()=>resolve('p1 resolved...'),1000);
    });
    var p2 = new Promise((resolve,reject) => {
        console.log('p2...');
        setTimeout(()=>resolve('p2 resolved...'),2000);
    });
    var p3 = new Promise((resolve,reject) => {
        console.log('p3...');
        setTimeout(()=>resolve('p3 resolved...'),3000);
    });
    
    Promise.race([p1,p2,p3]).then((val)=>console.log(val),(reason)=>console.log(reason));
    
    p1...
    p2...
    p3...
    Promise { <state>: "pending" }
    p1 resolved...

    5.Promise.resolve与Promise.reject

    Promise.resolve是将给定的参数转换成一个Promise对象,如下所示

    Promise.resolve(arg);//等同于new Promise((resolve)=>resolve(arg))
    omise.resolve('resolve convert...').then((val)=>console.log(val));
    Promise { <state>: "pending" }
    resolve convert...

    根据给定的参数类型不同,Promise.resolve有不同的动作:

    A、参数为Promise实例,则直接返回该实例

    B、参数为空,执行返回一个resolved状态的新Promise实例

    C、参数为普通的数值或对象,则直接返回一个resolved状态的新Promise实例,如下所示

    Promise.resolve({x:1}).then((val)=>console.log(val));
    Promise { <state>: "pending" }
    Object { x: 1 }

    D、参数为thenable对象,既对象实现了then方法,此时返回一个新Promise实例并立即执行对象then方法,如下所示

    var thenableObj = {
        then(resolve,reject){
            reject('test...');
        }
    };
    Promise.resolve(thenableObj).then(null,(reason)=>console.log(reason));
    
    Promise { <state>: "pending" }
    test...

    Promise.reject与Promise.resolve的用法一致,只是返回的Promise实例的状态为rejected,如下所示

    Promise.reject('reject convert...').then(null,(reason) => console.log(reason));
    Promise { <state>: "pending" }
    reject convert...

    6.给原生Promise对象扩展方法,如下所示

    //一下两个函数来自raunyifeng博客
    Promise.prototype.done = function (onFulfilled, onRejected) {
      this.then(onFulfilled, onRejected)
        .catch(function (reason) {
          setTimeout(() => { throw reason }, 0);
        });
    };
    该方法只要执行就可以捕获前面调用链中的错误
    Promise.prototype.finally = function (callback) {
      let P = this.constructor;
      return this.then(
        value  => P.resolve(callback()).then(() => value),
        reason => P.resolve(callback()).then(() => { throw reason })
      );
    };
    该方法不管Promise的实例的状态是否改变都会执行回调函数
  • 相关阅读:
    python脚本 – 删除指定天数前的文件
    java 获取屏幕的分辩率
    解决Multi input/output stream coders are not yet supported(org.apache.commons.compress)
    解决tomcat at org.apache.tomcat.util.buf.CharChunk.append(CharChunk.java:355)
    org.quartz.jobStore.misfireThreshold = 60000
    python list 自定义排序
    利用pycron在windows上实现cron定时任务
    [Selenium+Java] Scroll UP or Down a page in Selenium Webdriver
    Python获取硬件信息(硬盘序列号,CPU序列号)
    ChromeDriver自动更新、FirefoxDriver自动更新、InternetExplorerDriver自动更新(Java+Python)
  • 原文地址:https://www.cnblogs.com/zmxmumu/p/5591827.html
Copyright © 2011-2022 走看看