为什么使用Promise
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise对象的两个特点
(1)对象的状态不受外界影响。Promise对象是一个异步操作,有3种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果能决定当前属于哪个状态,其它操作无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
Promise基本用法
const promise = new Promise((resolve, reject)=>{
setTimeout(function(){
console.log('成功')
resolve(value)
},2000)
})
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数:
(1)resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
(2)reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
//new一个Promise对象
const promise = new Promise((resolve, reject)=>{
setTimeout(function(){
console.log('成功')
resolve('value')
},2000)
})
//
promise.then((value)=>{
console.log(value)//value
})
then方法接受两个回调函数的参数,第一个是状态改变成resolve时候调用的,第二个是reject时候调用的,第二个函数不是必写的
const promise = new Promise((resolve, reject) => {
console.log('Promise')
resolve()
})
promise.then(res=>{
console.log('resolve')
})
console.log('win')
//Promise
//win
//resolve
从上述代码中可以看出,Promise新建后立即执行,可是then方法是因为回调函数,只有当同步函数执行完了以后才会执行,所以在最后执行。
Promise中then()链式写法
then方法返回的是一个新的Promise实例,当发生异步操作时,then会返回一个新的Promise对象,这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。
function test1() {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve('Promise1')
},2000)
})
}
function test2() {
return new Promise((resolve, reject) => {
resolve('Promise2')
})
}
test1().then(res=>{
console.log(res)
return test2()
}).then(res=>{
console.log(res)
})
//Promise1
//Promise2
上面的代码使用then方法,test1中从在异步操作,所以他要等2秒,等到test1返回结果了以后才会去执行下一个then方法。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。
catch()用法
catch()方法是用于指定发生错误时的回调函数。
function test (){
return new Promise((resolve, reject)=>{
console.log(value)
})
}
test().then(res=>{
console.log('成功')
}).catch(err=>{
console.log('失败',err)
})
//失败 ReferenceError: value is not defined
上面代码中test返回一个新的Promise对象,如果没有发生错误,执行成功,Promise对象的状态是resolved,会调用then方法,如果test函数返回Promise对象的状态rejected,就会调用catch()方法来抛出异常,在执行这个then的链式的过程中,只要出现异常都会被catch()捕捉到的。
finally()用法
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
function test (){
return new Promise((resolve, reject)=>{
console.log('value')
})
}
test().then(res=>{
console.log('成功')
}).catch(err=>{
console.log('失败',err)
}).finally(()=>{
console.log('执行finally')
})
//成功
//执行finally
上面代码中,不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数,finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
all() 用法
all()方法是将多个Promise 的实例包装成一个新的Promise 实例,all接受一个数组作为参数,数组的参数都是一个个Promise实例。
function test1() {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve('Promise1')
},2000)
})
}
function test2() {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve('Promise2')
},2000)
})
}
Promise.all([test1(),test2()]).then(res=>{
console.log(res)
})
//[Promise1,Promise2]
上面代码中,all()的参数就是2个Promise实例的数组,他只有等所有的实例状态都变成fulfilled或者如何一个实例变成rejected,才会去调用all()方法后面的回调函数,all()方法会把所有实例为fulfilled状态的值以数组类型的返回给后面的then()方法。
function test1() {
return new Promise((resolve, reject) => {
throw new Error('报错了');
resolve('Promise1')
}).catch(err=>{
//Error: 报错了
console.log(err)
})
}
function test2() {
return new Promise((resolve, reject) => {
resolve('Promise2')
}).catch(err=>{
console.log(err)
})
}
Promise.all([test1(), test2()]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
//[undefined, "Promise2"]
上面代码中可以看出,test1中出现错误,在test1中直接catch()出去了,但是all()方法还是会执行then后面的回调函数,只不过是发生错误的Promise实例返回undefined,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。
function test1() {
return new Promise((resolve, reject) => {
throw new Error('报错了');
})
}
function test2() {
return new Promise((resolve, reject) => {
resolve('Promise2')
})
}
Promise.all([test1(), test2()]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
//Error: 报错了
})
上面代码中可以看出,如果作为参数的 Promise 实例,没有自己定义catch方法,那么一旦被rejected,会触发Promise.all()的catch方法。
race()用法
race()方法同样是将多个Promise实例包装成一个新的Promise实例,它接受的参数和all()方法的参数是一样的,不同的是race()方法是只要有作为参数的Promise实例有任意一个发生改变了,他就会去执行race()方法后面的then()方法的回调函数。
function test1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise1')
}, 2000)
})
}
function test2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise2')
}, 2000)
})
}
Promise.race([test1(), test2()]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
//Promise1
上面我们可以看到,作为Promise实例的test1的状态优先发生改变,Prromise.race()就直接执行了then()里面的操作。
下面用的比较少,简单简绍一下
allSettled() 接受一个数组的Promise实例作为参数,它不关心异步操作的结果,只关心这些异步操作有没有完成。
any() 接受一个数组的Promise实例作为参数,any()和race()的方法很像,唯一不同的就是any()方法不会因为某个Promise变成rejected状态而结束。只要Promise实例参数中有一个是fulfilled,那么any()就返回Promise对象的fulfilled。只有所有的操作都变成rejected,那么any()就会抛出一个错误。
resolve()主要是把现有的对象转换成一个Promise对象
以上就是平时在项目用到Promise的一些方法。