浅谈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中还有很多其他用法,后续有时间再更新~

浙公网安备 33010602011771号