promise

不废话,上来就整,先看一下写法,new了个构造函数,传了两个匿名函数参数resolve,reject,分别是成功和失败,需要注意的一点就是new完之后就开始执行,很果断,不带犹豫的,这就是promise的脾气啊

{
     let p=new Promise((resolve,reject)=>{
          setTimeout(
              ()=>{
                 console.log('2');
                 resolve('success');
              },0);
     }).then((res)=>{
            console.log(res+1);
            return 3;
     }).then((res)=>{
           console.log(res);//3
   });
}

下面来一段img加载的代码,由于promise脾气太过于耿直,so,咱们把他扔到function里,把他return出去,这样就可以随时随用了,再也不用担心promise的脾气了,这段代码里加了一个then,then是什么鸟呢,他是promise上面一个方法,传两个匿名函数,一个成功,一个失败,在promise的resolve里面传的参数就会传到then的成功函数里,同样的reject也是

{
     function loadImg(url){
          const p=new Promise((resolve,reject)=>{
                let img=new Image();
                img.onload=function (){
                    resolve('加载成功');
                    console.log('success');
                };
                img.onerror=function (){
                    reject('加载失败');
                    console.log('error');
                };
               img.src=url;
               console.log(url);
          });
          return p;
      }
  
      //加载图片
       loadImg('http://imgsrc.baidu.com/imgad/pic/item/
       267f9e2f07082838b5168c32b299a9014c08f1f9.jpg').then((suc)=>{
          console.log(suc)
          return loadImg('http://imgsrc.baidu.com/');
          //成功
       },(err)=>{
          console.log(err);
          //失败
       }).then(suc=>{
          console.log(suc);
          alert(suc);
       },err=>{
          console.log(err);
          alert(err);
       });

       //上面就是resolve方法使用,当然reject也是这种用法,
       then真是犀利的 一B啊
}
  • Promise.resolve方法可以将不是promise的对象转化为promise对象
//例如
Promise.resolve(1)
//相当于
new Promise(resolve=>resolve(1));

可以传4种类型的参数

  1. 不传参数
    Promise.resolve().then(()=>{
      //执行code
    });
    
  2. 传promise的实例 将实例的结果原封不动的返回出去
    Promise.resolve(new Promise((resolve,reject)=>{reject(2)})).catch(err=>{
      console.log(err);//2
    });
    
  3. 传一个带有then方法的对象,那么会先执行then的方法,并且这个方法里必须执行resolve或者reject方法,来改变状态,不然不会执行下去
     // 如果本地有数据就不请求,没有就请求
    let data="";
    let thenable={
     then(resolve,reject){
       setTimeout(()=>{
         resolve(14);
       },1000);
     }
    }
    
    let p=data?Promise.resolve(data):Promise.resolve(thenable)
    
    p.then(res=>{
     console.log(res)
    });
    
  4. 除去上面三种情况的其他值
    Promise.resolve("4").then(res=>{
      console.log(res);
    })
    
  • Promise.reject方法也会返回一个新的 Promise 实例,该实例的状态为rejected
//传一个promise实例
Promise.reject(new Promise((resolve,reject)=>{reject(42)})).catch(res=>{
  res.catch(e=>{
    console.log(e);//42
  })
});
//传一个字符串
Promise.reject("哈哈").catch(err=>{
  console.log(err);//哈哈
});

通过上面例子可以看出Promise.reject无论传什么参数,都会原封不动地作为reject的理由,变成后续方法的参数

  • look一下all的用法,感觉这特么的就是个大招啊,异步执行的,并且在所有异步操作执行完后才执行回调,谁拖大腿根听谁的
{
    function getImg(url){
       const p=new Promise((resolve,reject)=>{
           let img=new Image();
           img.src=url;
           img.onload=function (){
                resolve('suc');
           };
           img.onerror=function (){
                reject('err');
           };
       });
       return p;
    }

    function hideBanner(flag){
       let p=new Promise((resolve,reject)=>{
          setTimeout(()=>{
             if (flag){
                 resolve('隐藏成功');
             }else{
                 reject('失败');
             }
           },1000);
           console.log('隐藏图片');
       });
       return p;
    }
    Promise.all([getImg('http://imgsrc.baidu.com/imgad/pic/item/
    267f9e2f07082838b5168c
    32b299a9014c08f1f9.jpg'),hideBanner(true)]).then((results)=>{
       console.log(results);//["suc", "隐藏成功"]
    });
    //传的这个URL路径是错误的并不会加载成功,所以会走reject
                
    Promise.all([getImg('http://imgsrc.baidu.com
    /pic/item/267f9e2f07082838b51
    68c32b8f1f9.jpg'),hideBanner(false)]).then((results)=>{
        console.log(results);
    }).catch(e=>{
        console.log(e);//err
    });
    //promise真是个够义气的哥们啊,要么都成功,要么一个失败,就都失败
}
  • 再see一下race的方法,这个也是异步的,但是跟all不同的是,谁跑的快听谁的,谁跑到终点就开始执行then了
{
    function timeout1(){
       let p=new Promise((resolve,reject)=>{
           setTimeout(()=>{
               resolve('我是1s就执行');
           },1000);
        });
        return p;
    }

    function timeout2(){
       let p=new Promise((resolve,relect)=>{
           setTimeout(()=>{
              console.log('console出来的==》我是2s就执行');
              resolve('我是2s就执行');
           },2000);
       });
       return p;
    }

    Promise.race([timeout1(),timeout2()]).then((results)=>{
        console.log(results);//我是1s就执行
    });
    //很明显,timeout1先执行完,所以then就输出timeout1的成功参数,那么就别以为timeout2就不执行了,其实人家也执行着呢,只不过没有在then里体现出来,那就有人问了,这玩意有个鸟用啊,你还真说对了,这玩意还真有个鸟用,下面看一下请求图片的时候,或者请求借口的时候时间长了如果还没有成功,那就是成功的挂掉了,我们得给用户一个反馈
    function getImg(url){
       const p=new Promise((resolve,reject)=>{
             let img=new Image();
             img.src=url;
             img.onload=function (){
                 resolve('suc');
             };
             img.onerror=function (){
                 console.log('gua');
                //reject('err');
                //注意这里,因为要在timeout上做失败处理,所以这里就不要执行reject了,因为一旦把状态变为rejected,那么就不会执行timeout了
             };
       });
       return p;
   }

   function timeout(){
       let p=new Promise((resolve,reject)=>{
           setTimeout(()=>{
               reject('诶哟~挂掉了');
           },5000);
       });
       return p;
   };
   Promise.race([getImg('http://imgsrc.baidu.com/imgad/hehe'),timeout()]).then((result)=>{
      console.log(result);
   }).catch(e=>{
      console.log(e);//诶哟~挂掉了
   });
}
  • allSettled的方法

有时候我们需要一组异步的操作都结束了,无论其中的每一个是失败还是成功,再进行下一步的操作,就可以用allSettled方法

const resolve=Promise.resolve(12);
const reject=Promise.reject(-1);

Promise.allSettled([resolve,reject]).then((res)=>{
  console.log(res)
/*
  [
    {"status": "fulfilled","value": 12},
    {"status": "rejected","reason": -1}
  ]
*/
})

allSettled接受一个数组,执行完,他的状态只会是fulfilld,所以只会执行then的第一个匿名函数,执行完得到的结果是一个数组,分别是带有状态的json,可以来区分执行完的状态失败和成功

/*
  [
    {"status": "fulfilled","value": 12},
    {"status": "rejected","reason": -1}
  ]
*/
//过滤状态成功的结果
const fulfilledRes=res.filter(item=>item.status==="fulfilled");
//过滤状态失败的结果
const rejectRes=res.filter(item=>item.status==="reject");
  • any方法,接受一个数组参数,里面都是promise实例,最后返回一个promise实例

any方法和race方法很像,但是race是根据返回结果时间来执行的,而any是根据状态执行的,只要一组中其中一个的状态变为fulfilled,那么any的状态就会变成fulfilled,或者一组中所有的成员都变成了reject状态,那么any也会变成reject状态

const resolve=Promise.resolve(12);
const reject1=Promise.reject(-1);
const reject2=Promise.reject(-2);
const reject3=Promise.reject(-3);
//一个状态为`fulfilled`,那么`any`的状态就会是`fulfilled`
Promise.any([reject1,resolve]).then((res)=>{
  console.log(res);//12
});
//所有的实例状态都是`reject`,`any`的状态也是`reject`
Promise.any([reject1,reject2,reject3]).catch((results)=>{
  console.log(results);//AggregateError: All promises were rejected
  console.log(results.errors);//[-1, -2, -3]
});

通过以上结果可以看出,如果参数一组实例都是reject状态,那么返回的结果results是无法直接显示结果的,需要用results.errors才能显示出来返回的结果

  • 再来讲一下catch的方法
  //在上面的例子中可以看出,catch是可以顶替reject对应的匿名函数的,那么还有一个作用,是用来顶替try catch的,来看一下下面的例子
{
     let p=new Promise((resolve,reject)=>{
           reject('error');
           show();//未定义这个show函数
         }).then(res=>console.log(res)).catch(e=>{
            console.log(e);//error
    //下面还可以执行别的代码,如果不用catch的话,js报错就挂掉了,不往下执行了,并且过滤掉了show这个错误
      console.log('继续执行代码');
      });
}
 {
     let p=new Promise((resolve,reject)=>{
             show();//未定义这个show函数
          }).then(res=>console.log(res)).catch(e=>{
             console.log(e);//show is not defined
            //下面还可以执行别的代码,如果不用catch的话,js报错就挂掉了,不往下执行了,状态不是reject和resolve的话,不会过滤掉show这个错误
            console.log('继续执行代码');
     });
}
 //在then里报错,还是会进到catch里面,不会影响代码继续执行
{
   let p=new Promise((resolve,reject)=>{
            resolve('success');
       }).then(res=>{
            console.log(res);
           show();//未定义这个show函数
       }).catch(e=>{
             console.log(e);//show is not defined
          //下面还可以执行别的代码,如果不用catch的话,js报错就挂掉了,不往下执行了
            console.log('继续执行代码');
      });
 });
}
  • finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
{
   let p=new Promise((resolve,reject)=>{
            resolve('success');
       }).then(res=>{
            console.log(res);
       }).catch(e=>{
             console.log(e);
       }).finally(()=>{
          //执行代码
       });
 });

finally方法传一个回调函数,但是不接受任何参数,无论Promise的状态到底是fulfilled还是rejected,执行完then或者catch之后都会执行finally,所以与状态无关

finally的实现很简单,其实就是又一次执行了then的方法

class Promise{
  finally=(cb)=>{
    return this.then(
      value=>this.resolve(cb()).then(()=>value)),
      reason=>this.resolve(cb()).then(()=>reason)
  }
}

从上面的实现还可以看到,finally方法总是会返回原来的值。

// resolve 的值是 2
Promise.resolve(2).finally(() => {})

关于promise就介绍这么多,希望对你有所帮助,如果想看更详细的资料,请狠狠的点击我

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 回调 把一个函数A传给另一个函数B调用,那么A就是回调函数 具名回调写法 匿名回调写法 多层嵌套的匿名回调(回调地...
    lyp82nkl阅读 2,485评论 0 0
  • 本文采用es6语法实现Promise基本的功能, 适合有javascript和es6基础的读者,如果没有,请阅读 ...
    tenor阅读 355评论 0 1
  • 00、前言Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区...
    夜幕小草阅读 2,154评论 0 12
  • 摘自:阮一峰 http://es6.ruanyifeng.com/#docs/promise 一、首先,我们要弄明...
    泡杯感冒灵阅读 806评论 0 4
  • 搬运学习,非原创 Promise 的含义 Promise对象有以下两个特点。 (1)对象的状态不受外界影响。Pro...
    wsgdiv阅读 210评论 0 0