promise是什么,怎么运行,长什么样,有哪些方法,解决什么问题
1、Promise 是什么?
Promise是异步编程的一种解决方案。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。链式调用中的 promise 们就像俄罗斯套娃一样,是嵌套起来的,但又像是一个栈,每个都必须从顶端被弹出。链式调用中的第一个 promise 是嵌套最深的一个,也将是第一个被弹出的。
标准写法
let a = new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve('成功') // 数据处理完成
// reject('失败') // 数据处理出错
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失败
)
2、promise 的方法
2.1关于then,catch,finally
六个方法 then,catch,finally是promise的实例化方法 resolve,reject 和 all,race是静态方法
- then和catch同级 catch用来处理异常
- then之后有resolve和reject (resolve和reject是属于promise的静态方法,不是then的方法)
- resolve和reject(决定谁来继续):
- then=>有resolve和reject 也就是每次向下一个函数传参的时候就会有成功和失败的选择传参
- resolve等于成功 resolve的东西,一定会进入then的第一个回调,肯定不会进入catch
- reject等于失败 reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
then:用来链式调用方法 - 类似不停的将上个函数作为参数传到下一个函数中进行链接作为then方法中函数的参数,then可接受两个参数,第一个处理Resolved状态的函数,第二个处理Rejected函数。如果只想处理成功,或者失败,只有一个参数则表示状态改变就执行,不区分状态结果。
- catch:可以和then的第二个参数里面一样,但是最重要的作用就是在执行resolve的回调,也就是then的第一个参数的时候,如果抛出了异常,那么并不会报错卡死,就会进入这个catch方法。
- finally:无论是否成功都会执行
function c(){}
function e(){}
function w(){}
functiowen data(){}
c()
.then(function(data){
return e(data);
}).then(function(data){
return w(data);
}).then(function(data){
console.log(data);
});
//简化代码
c()
.then(e)
.then(w)
.then(function(data){
console.log(data);
});
2.2关于catch和reject
- catch和reject的主要区别就是,reject是抛出异常catch如果在then的第一个函数里抛出了异常,后面的catch能捕获到,而then的第二个函数捕获不到。因此,建议总是使用catch方法,而不使用then方法的第二个参数。
- 过早地处理被拒绝的 promise 会对之后 promise 的链式调用造成影响。不过有时候我们因为需要马上处理一个错误也只能这样做。另一方面,在没有迫切需要的情况下,可以在最后一个.catch() 语句时再进行错误处理,这种做法更加简单。
2.3关于all和race
all和race(监控多个promise):
- 当多个promise,状态发生变化的时候,这两个方法会给出不同的处理方式
Promise.all(): - 当可迭代对象中的所有成员都是已完成的Promise时,新的Promise的状态为fulfilled。而各个成员的决议结果会组成一个数组,传递给后续的已完成的回调函数。
- 当可迭代对象中的成员有一个是已拒绝的Promise时,新的Promise的状态为rejected。并且只会处理到这个已拒绝的成员,接下来的成员都会被忽略,其决议结果会传递给后续的已拒绝的回调函数。
Promise.race():
-
新的Promise实例的状态也与方法的参数有关,当参数的成员为空时,其状态为pending;当参数不为空时,其状态是最先被处理的成员的状态,并且此成员的决议结果会传递给后续相应的回调函数。(使用较少和all比较来说就是最先完成的就直接进入后续代码)
-
当我们加载多个图片时,一般不会使用连缀的方法,直接用all的方法,将图片放在一个数组来加载。
all的用法案例:
//使用promise加载
var arr=[];
for(var i=2;i<80;i++){
arr.push(loadImg("./img/"+i+"-.img"));
}
promise.all(arr).then(function(list){
console.log(list);
})
//这是不使用promise的加载
var arr=[];
var n=2;
loadImage("./img/"+i+"-.img");
function loadImage(){
var img=new Image();
img.addEventListener("load",loadHandler);
img.src=src;
}
function loadHandler(){
img.removeEventListener("load",loadHandler);
arr.push(img);
n++;
if(n>=80){
//console.log(arr);
finishHandler(arr);
return;
}
loadImage("./img/"+i+"-.img");
}
function finishHandler(){
}
红黄绿的promise用法案例
// 红黄绿 案例
function showLight(color,time){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve(color);
},time);
})
}
show();
function show(){
showLight("红",2000).then(function(color){
console.log(color);
return showLight("黄",2000);
}).then(function(color){
console.log(color);
return showLight("绿",2000);
}).then(function(color){
console.log(color);
show();
})
}
promise也可以用于防抖
//可以用于防抖 promise
function fn(){
console.log("aaa");
}
function interval(fn,time){
return new Promise(function(resolve,reject){
var ids=setTimeout(function(){
clearTimeout(ids);
resolve(fn);
},time)
})
}
function doneFn(){
interval(fn,2000).then(function(){
fn();
doneFn();
})
}
doneFn();
3.为什么promise中resolve和reject只能执行一个?
因为promise有三种状态分别是:
待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
已兑现(fulfilled): 意味着操作成功完成。
已拒绝(rejected): 意味着操作失败。
所以在初始化状态改变后不管是兑现还是拒绝都不会再次进入另外的状态
4.解决什么问题
最主要解决的问题就是回调地狱的问题,回调地狱就是我们异步任务中异步任务一层一层的嵌套。
关于一些拓展
可以参考下面博客