浅谈Promise的用法

Promise是什么呢?

   ES6中对它的定义是一个容器,里面保存着某个未来会结束的事件的结果。
   从语法上面来说,Promise是一个对象,从它可以获取异步操作的消息。

Promise对象的特点
  
     1、对象的状态不受外界影响。
         有三种状态,pending(进行中), fulfilled(成功), rejected(失败)。
         只有异步操作的结果可以决定当前是哪一种状态,其他的任何一种操作都不能改变当前状态。
      2、一旦状态发生改变,就不会再变,任何时候都可以得到这个状态。
          Promise状态的改变,只有两种可能,pending变为fulfilled, pending变为rejected。

看了定义是不是没什么感觉?我们直接在后台打印下Promise,看看它究竟是什么?

 

 这样可以直观的看出Promise是一个构造函数,还有自身的一些方法。

先创建一个promise

var promise = new Promise(function(resolve, reject){
     // 写个异步操作
     setTimeout(function(){
        console.log('异步操作')
        resolve('异步操作结果')
      }, 2000) 
})

Promise可以接收一个参数,是一个函数,并且又可以传入两个参数,resolve, reject。resolve是异步操作执行成功后的回调,reject则是失败后的回调。
或者按照标准讲,resolve是将Promise的状态置为fulfilled,reject是将Promise的状态置为rejected。
在上面的代码里,有执行一个异步操作。setTimeout两秒后输出结果,并且执行resolve的操作。

那么下面我们创建一个函数,实际操作一下~

function promiseFc(){
   var promise = new Promise(function(resolve, reject){
        setTimeout(function(){
          console.log('异步操作')
          resolve('我的异步操作返回')
        }, 2000);
   });
   return promise;
};

promiseFc();


在这个函数中,我们return了一个Promise对象,执行这个函数时会得到一个Promise对象。上面我们打印Promise时看到有then, catch方法。那么,我们就可以使用了。

promiseFc().then(function(data){
    console.log(data);
    
})

 我们看下输出结果吧。

 

 两秒输出异步操作,紧接着输出resolve我的异步操作返回。

这样的Promise在实际工作中有什么使用场景呢?


说下我的实际工作使用情况吧。很多时候我们会用到上传文件的操作,那么会遇到这种情况,上传文件过大,后端接口无法直接处理大文件怎么办呢?
这个时候会用到oss直传方法,我们先从后端同学那里拿到上传需要的osskey和签名之后再去上传。那么这个时候使用的场景就会用到Promise

具体实现方法(复制粘贴过来的,仅作为参考)

function beforeUpload(file, uploadOptions) {
    // file 原生的File对象,即将被上传的文件
    // uploadOptions 是 上传参数
    let promise = ajaxGetOSSToken(); // 函数自行实现,保证返回一个promise来就可以
    promise = promise.then((data) => {
    	uploadOptions.data = {
    		        name: file.filename,
			key: `${data.dir}${file.name}`,
			policy: data.policy,
			OSSAccessKeyId: data.accessid,
			success_action_status: 200
			signature: data.signature
    	};
    	uploadOptions.headers = {'X-Requested-With': null};// 需要跨域上传的话加这一段
    	uploadOptions.action = data.host;
    	return uploadOptions;
    });

    return promise;
}

 

上面仅使用了resolve的操作,看看reject的操作是如何的吧。

function getNumber(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            var num = 8; 
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字不符合条件');
            }
        }, 2000);
    });
    return p;            
}

getNumber()
.then(
    function(data){
        console.log('resolved');
        console.log(data);
    }, 
    function(reason, data){
        console.log('rejected');
        console.log(reason);
    }
);

定义了数字8,显然不符合条件,那么就会走reject的回调。

看下输出结果

 

 

返回的Promise对象函数中如果不是then的回调,catch会如何呢?还用刚刚的方法,只是将reject放在了catch里面。

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

看下执行结果

 

 

两次输出结果一样,说明其实它和then的第二个参数一样,用来指定reject的回调。

 

Promise的链式操作
  我们知道Promise的作用其中之一就是可以解决回调地狱问题。链式调用then方法。
  

function f1(){
        return new Promise(resolve=>{
            setTimeout(()=>{
                console.log('第一步');
                
                //异步逻辑已经执行完,必须要告诉外界我执行完了
                resolve();

            },1000)
        })
    }
    function f2(){
        return new Promise(resolve=>{
            setTimeout(()=>{
                console.log('第二步');
                
                //告诉外界我执行完了
                resolve();
            },1000)
        })
    }

    f1().then(res=>{
        //返回一个promise对象,然后链式调用then方法
        return f2();
    }).then(res=>{
        return f1();
    }).then(res=>{
        return f2();
    }).then(res=>{
        setTimeout(()=>{
            console.log('完成');
        },1000)
    })

  

 Promise的all方法
    Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
    当需要一次性请求多个接口时可用此方法。
     

Promise.all([f1,f2]).then(function([Result1,Result2]){
    // 这里写等这两个函数都成功返回数据才执行的业务逻辑
})

  

Promise的race方法 

 看字面意思,race就是比赛的意思。谁运行的快,以谁为准执行回调。

function getResult1(){
   var promise1 = new Promise(function(resolve, reject){
      setTimeout(function(){
          console.log('数据1')
           resolve('一秒钟')
      }, 1000)
})
 
return promise1
}

function getResult2(){
   var promise2 = new Promise(function(resolve, reject){
      setTimeout(function(){
          console.log('数据2')
           resolve('两秒钟')
      }, 2000)
})
 
return promise2
}


Promise.race([getResult1(), getResult2()]).then(function(result){
   console.log(result)
})

  输出结果为:



Promise中还有很多其他用法,后续有时间再更新~

 

 

 




 



 

posted @ 2021-08-18 10:57  Judy倩倩  阅读(288)  评论(0)    收藏  举报