Promise
什么是Promise呢
Promise是JS进行异步编程的新的解决方案,从语法上说,Promise是一个构造函数,从功能来说Promise对象用来封装一个异步操作并可以获取其结果
Promise状态
pending:未确定的,初始的状态
fulfilled:成功状态
rejected:失败状态
一个Promise对象只能改变一次,并且只能是pending状态变为其他的两种状态。无论成功还是失败,都会有一个结果数据。
Promise的执行流程
Promise的简单使用
//创建并定义一个新的Promise对象
const p = new Promise((resolve,reject)=>{
//执行异步操作
setTimeout(()=>{
//如果当前事件是偶数就代表成功,否则就代表失败
const time = Date.now();
if(time %2 == 0){
//成功的调用
resolve("成功了");
}else{
//失败了调用
reject("失败了");
}
},1000);
})
p.then(
value =>{ //接收得到成功的value的数据
console.log(value);
},
reason =>{//接收得到失败的reason的数据
console.log(reason);
}
)
为什么要使用Promise
1.指定回调函数的方式更加的灵活:
以前必须在启动异步任务之前就指定回调的函数,现在使用promise就很灵活,可以在之前,也可以在之后,甚至在异步任务结束之后在指定。
传统的回调函数:我们是先指定的回调函数,后面才启动的异步任务。
getHui=()=>{
console.log("这是get")
}
setHui=()=>{
console.log("这是set")
}
setHui =(a,getHui,setHui)=>{
setTimeout(()=>{
if(a === 0){
getHui();
}else(
setHui()
)
},1000)
}
我们在来看一下使用Promise:
//创建并定义一个新的Promise对象
const p = new Promise((resolve,reject)=>{
//执行异步操作
setTimeout(()=>{
//如果当前事件是偶数就代表成功,否则就代表失败
const time = Date.now();
console.log(time)
if(time %2 === 0){
//成功的调用
resolve("成功了");
}else{
//失败了调用
reject("失败了");
}
},1000);
});
setTimeout(()=>{
p.then(
value =>{ //接收得到成功的value的数据
console.log(value);
},
reason =>{//接收得到失败的reason的数据
console.log(reason);
}
)
},2000)
在上面的实例中,我们通过setTimeout控制回调函数是在异步操作已经执行完成之后才执行的,但我们惊喜的发现,这个还是可以获取到回调过来的数据。
2.解决回调地狱的问题
以前的回调经常会遇到,前一个的结果是后一个回调的参数,也就是嵌套调用回调函数。如果这样的回调比较多,代码维护起来就比较费劲,就会形成回调地狱。
比如:
那我们使用Promise的时候,就可以很好的解决这个问题:
虽然看起来代码好像也没有少多少,但是整体上看着还是比嵌套调用更加工整。便于维护,而且使用Promise可以使用异常穿透,也就是在最后用.catch来接收整个嵌套回调所暴漏的错误。
但是这样还是有回调函数,所以解决回调函数的最终方法:
async / await
async
作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行,但是该函数返回的是一个Promise对象。
await
await即等待,他后面跟着一个表达式。它只能在异步函数 async function中使用,否则会报错。可以返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。
await表达式会暂停当前 async function的执行,等待Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function,若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise。
Promise的相关API
Promise.prototype.then(onFulfilled, onRejected)
添加解决(fulfillment)和拒绝(rejection)回调到当前 promise, 返回一个新的 promise, 将以回调的返回值来resolve.
p.then(
value =>{ //接收得到成功的value的数据
console.log(value);
},
reason =>{//接收得到失败的reason的数据
console.log(reason);
}
)
接着我们看一下.then的返回值的新Promise的 状态是由什么决定的。
1.如果抛出异常,新Promise变为rejected,也就是失败的状态,reason为抛出的异常
2.如果返回的是非Promise的任意值,新Promise变为resolved,也就是成功的Promise,value为返回的值
3.如果返回的是另一个新Promise,那么该新的Promise的状态就是返回的状态。
接下来看一下链式调用then的需要注意的事情。
先来看一下这段代码:
const c = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("这是最后一个");
resolve(5);
},1000);
}).then(value => {
console.log("第一个的值"+value);
resolve(2);
});
我们在运行的时候发现:
在then的时候并不能调用resolve,这是因为then本身并没有resolve和reject这两个回调函数,只能使用return对其进行返回,如果在其中处理相关的异步方法,最好还是返回Promise对象,在其中进行异步操作。
Promise.prototype.catch(onRejected)
catch其实就是做错误处理的,Promise会错误穿透,在then的链式调用中一般会使用catch处理异常
p1.then(function(value) {
console.log(value); // "Success!"
throw 'oh, no!';
}).catch(function(e) {
console.log(e); // "oh, no!"
})
Promise.all(iterable)
这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。
如下:只有当p ,p1 ,p2这三个Promise对象全部返回成功了,newP才是成功,一旦其中一个失败,newP就失败。
const newP = Promise.all([p,p1,p2])
Promise.race(iterable)
当iterable参数里的任意一个子promise被成功或失败后,该函数就立即被执行,返回一个新的Promise,该状态就是子Promise返回的状态。
如以下代码,promise2率先执行完成,因此race就会执行,并且返回失败的Promise对象。
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
},reson =>{
console.log(reson)}
);
//结果:two