概述
概念上说,Promise是异步编程的一种解决方案。
从语法上说,Promise是一个对象,可以从他获取异步操作的消息。
状态
Promise对象有三种状态:
1. pending (进行中)
2. fulfilled(已成功)
3. rejected (已失败)
> 特点
Promise对象有两个特点:
1. 对象的状态不受外界印象。Promise对象的状态只有异步操作的结果可以决定
2. 对象的状态改变就不会再变。Promise对象有两种状态改变,一是从pending到resolved,二是从pending到rejected。这两种状态只要发生一种,就会一直保持这个结果。
> 缺点
1. Promise一旦执行,无法取消。
2. Promise如果不设置回调函数,其内部抛出的错误不会反应到外部
3. pending状态,无法得知目前进展到哪一个阶段
参数
Promise接受一个函数作为参数,这个函数的两个参数分别是resolve和reject。
1. resolve -> 将Promise对象的状态从pending变为resolved,并且将异步操作成功返回的结果作为参数传递出去
2. reject -> 将Promise对象的状态从pending变为 rejected,并且将异步操作返回的错t误作为参数传递出去
then方法
then方法接收两个函数作为参数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数。两个函数只有一个会被调用。
1 let p = new Promise((resolve,reject) => { 2 resolve() 3 }) 4 p.then(() => { 5 console.log("then方法的第一个参数") 6 },() => { 7 console.log("then方法的第二个参数") 8 }) 9 .catch(() => { 10 console.log("catch方法") 11 })
结果输出:
then方法的第一个参数
1 let p = new Promise((resolve,reject) => { 2 reject() 3 }) 4 p.then(() => { 5 console.log("then方法的第一个参数") 6 },() => { 7 console.log("then方法的第二个参数") 8 }) 9 .catch(() => { 10 console.log("catch方法") 11 })
结果输出:
1 let p = new Promise((resolve,reject) => { 2 setTimeout(() => { 3 console.log("Promise ----- p") 4 resolve() 5 },1000) 6 }) 7 let p1 = new Promise((resolve,reeject) =>{ 8 console.log("Promise ----- p1") 9 resolve(p) 10 }) 11 p1.then(res => { 12 console.log("then方法的第一个参数") 13 }) 14 .catch(() => { 15 console.log("catch方法") 16 })
返回结果的输出顺序:
Promise ----- p1
(两次输出之间间隔1秒)
Promise ----- p
then方法的第一个参数
链式调用
1 let p = new Promise((resolve,reject) => { 2 resolve() 3 }) 4 p.then(() => { 5 console.log("第一个then方法") 6 }) 7 .then(() => { 8 console.log("第二个then方法") 9 }) 10 .then(() => { 11 console.log("第三个then方法") 12 }) 13 .then(() => { 14 console.log("第四个then方法") 15 }) 16 .then(() => { 17 console.log("第五个then方法") 18 })
输出结果:
catch方法
发生错误时的回调函数。Promise对象的错误具有向后传递的性质,前面的错误(包括then方法中的错误或者前面一个catch中的错误)总是会被下一个catch捕获(捕获前面没有被捕获的错误,包括then的回调函数中抛出的错误)。
1 let p = new Promise((resolve,reject) => {
2 reject()
3 })
4 p.then(() => {
5 console.log("then方法的第一个参数")
6 })
7 .catch(() => {
8 console.log("catch方法")
9 })
结果输出:
catch方法
catch捕捉then方法中的错误
1 let p = new Promise((resolve,reject) => { 2 resolve() 3 }) 4 p.then(() => { 5 console.log("then方法的第一个参数") 6 throw new Error("then 错误") 7 }) 8 .catch(() => { 9 console.log("catch方法") 10 })
输出结果:
then方法的第一个参数
catch方法
catch向后传递的特性
1 let p = new Promise((resolve,reject) => { 2 reject() 3 }) 4 p.then(() => { 5 console.log("then方法的第一个参数") 6 }) 7 .catch(() => { 8 console.log("第一个catch方法") 9 throw new Error("catch错误") 10 }) 11 .then(() => { 12 console.log("第二个then方法") 13 }) 14 .catch(() => { 15 console.log("第二个catch") 16 })
输出结果:
第一个catch方法
第二个catch
finally方法
不管Promise对象的状态是什么都会执行的操作。finally方法的回调函数不接受任何参数,则没有办法知道前端Promise的具体状态,换句话说finally不依赖于Promise的执行结果
1 let p = new Promise((resolve,reject) => { 2 resolve() 3 }) 4 p.then(() => { 5 console.log("第一个then方法") 6 }) 7 .catch(() => { 8 console.log("第一个catch方法") 9 }) 10 .finally(() => { 11 console.log("finally") 12 })
输出结果:
第一个then方法
finally
1 let p = new Promise((resolve,reject) => {
2 reject()
3 })
4 p.then(() => {
5 console.log("第一个then方法")
6 })
7 .catch(() => {
8 console.log("第一个catch方法")
9 })
10 .finally(() => {
11 console.log("finally")
12 })
输出结果:
第一个catch方法
finally
all方法
all方法用于将多个Promise实例包装成一个新的Promise实例。新的Promise实例的状态由组成它的Promise实例的状态共同决定(个人感觉有点类似于&&运算符)。
1> 多个Promise实例的状态都变成已完成(resolved)状态,新的Promise实例的状态才会变成已完成状态,并且将多个Promise实例的返回值组成一个数组传递给新的Promise的回调函数
2> 多个Promise实例中,只要有一个实例的状态变成rejected,新的实例的状态就会变成rejecte,并且将第一个状态为rejected的实例的返回值传递给新的Promise实例的回调函数。
1 let p1 = new Promise((resolve,reject) => { 3 resolve("p1") 4 }) 5 let p2 = new Promise((resolve,reject) => { 7 resolve("p2") 8 }) 9 let p3 = new Promise((resolve,reject) => {11 resolve("p3") 12 }) 13 14 let p = Promise.all([p1,p2,p3]) 15 p.then(res => { 16 console.log('返回结果res -->',res) 17 }) 18 .catch((error) => { 19 console.log('返回错误error -->',error) 20 })
输出结果:
返回结果res --> (3) ["p1", "p2", "p3"]
1 let p1 = new Promise((resolve,reject) => { 3 resolve("p1") 4 }) 5 let p2 = new Promise((resolve,reject) => { 7 reject("p2") 8 }) 9 let p3 = new Promise((resolve,reject) => {11 resolve("p3") 12 }) 13 14 let p = Promise.all([p1,p2,p3]) 15 p.then(res => { 16 console.log('返回结果res -->',res) 17 }) 18 .catch((error) => { 19 console.log('返回错误error -->',error) 20 })
输出结果:
返回错误error --> p2
race方法
跟all方法相同,将多个Promise实例包装成一个新的Promise实例,只不过和all方法不同的是,race是哪个Promise先返回结果就取哪个Promise的结果,不会等待全部的Promise实例执行完。
all方法返回的结果和参数中数组的有关系,但是race方法的返回结果和Promise实例的执行顺序有关。
1 let p1 = new Promise((resolve,reject) => { 2 resolve("p1") 3 }) 4 let p2 = new Promise((resolve,reject) => { 5 resolve("p2") 6 }) 7 let p3 = new Promise((resolve,reject) => { 8 resolve("p3") 9 }) 10 11 let p = Promise.race([p1,p2,p3]) 12 p.then(res => { 13 console.log('返回结果res -->',res) 14 }) 15 .catch((error) => { 16 console.log('返回错误error -->',error) 17 })
输出结果:
返回结果res --> p1
1 let p1 = new Promise((resolve,reject) => { 2 setTimeout(() => { 3 resolve("p1") 4 },1000) 5 }) 6 let p2 = new Promise((resolve,reject) => { 7 setTimeout(() => { 8 resolve("p2") 9 },1500) 10 }) 11 let p3 = new Promise((resolve,reject) => { 12 setTimeout(() => { 13 reject("p3") 14 },500) 15 }) 16 17 let p = Promise.race([p1,p2,p3]) 18 p.then(res => { 19 console.log('返回结果res -->',res) 20 }) 21 .catch((error) => { 22 console.log('返回错误error -->',error) 23 })
输出结果:
返回错误error --> p3
小记:
catch和then方法的第二个参数的区别:
我们知道,then方法的是第二个参数和catch都是Promise状态变为rejected时执行的回调函数,但是我们一般不用then方法的第二个参数而总是使用catch方法,这是因为catch方法可以捕获到then方法中的错误,而then方法的第二个参数是捕捉不到的。
...