Promise
Promise的在项目和面试中都会用到,看了别人写的一些对Promise的使用以及自己的理解,现在整理归纳一些内容。
- 1、什么是Promise
js的代码是单线程,但是浏览器事件、js网络就必须是异步操作,都必须是异步执行。Promise可以异步计算,console.dir(Promise)来看看Promise是什么。
可以说Promise是个构造函数,有一些all、race、reject、resolve等一堆方法。
prototype中含有catch 和then,用Promise new出来的对象肯定就有then、catch方法。
2、Promise有哪些函数
Promise常用的就是 resolve、reject 、all、race
先来说说Promise的状态
Promise对象的特点
(1)有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是promise这个名字的由来“承若”;
(2)一旦状态改变就不会再变,任何时候都可以得到这个结果,promise对象的状态改变只有两种:pending—>fulfilled,pending—>rejected。这时就称为resolved(已定型)。如果改变已经发生了,你再对promise对象添加回调函数,也会立即得到这个结果,
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
3、Promise的用法
是一个构造函数,这个构造函数里有两个参数,分别是:resolve(成功之后的回调函数)、reject(失败之后的回调函数)。
因为promise表示的是一个异步操作,每当我们new一个promise实例,就表示一个具体的异步操作,那么这个异步操作的结果就只能有两种状态:成功/失败,两者都需要回调函数resolve/reject返回。所以内部拿到操作的结果后,无法使用return把操作结果返回给调用者,这时候只能用回调函数的形式来把成功或失败的结果返回给调用者。
**promise.resolve()**使用
let promise =new Promise((resolve,reject)=>{
resolve(1111);
// reject(22222);
});
promise.then((response)=>{
console.log("success");
console.log(response);
}).catch(error=>{
console.log("failed");
console.log(error);
});
得到的是
**promise.reject()**使用
let promise =new Promise((resolve,reject)=>{
// resolve(1111);
reject(22222);
});
promise.then((response)=>{
console.log("success");
console.log(response);
}).catch(error=>{
console.log("failed");
console.log(error);
});
得到了
上述两个例子可以知道 resolve–>then reject—>catch。Promise会自动捕获内部异常,并交给rejected响应函数处理
Promise.all() 批量执行
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务1执行完成');
resolve('随便什么数据1');
}, 3000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务2执行完成');
resolve('随便什么数据2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务3执行完成');
resolve('随便什么数据3');
}, 4000);
});
return p;
}
Promise.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
}).finally(function(results) {
console.log("finally....");
});
all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。
有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,是不是很酷?有一个场景是很适合用这个的,一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。
Promise.race() 采用上面的runAsync1()runAsync2()runAsync3()
Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
}).finally(function(results) {
console.log("finally....");
});
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,这个词本来就是赛跑的意思。这三个异步操作并行执行的。2秒后runAsync2已经执行完了,此时then里面的就执行回调,runAsync1()和runAsync1()仍旧再执行。于是再过1秒后,输出了他们结束的标志。 这个race有什么用呢?使用场景还是很多的,比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:
4、Promise的缺点
4.1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。
4.2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
4.3、当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。