前言
Promise 是ES6 新增的一个异步调用解决方案,它的出现是为了解决异步函数的
回调地狱
的问题。
什么是 Promise?
从语法层面 来说 Promise 是一个构造函数
,从功能上来说 Promise 对象用来封装一个异步操作
,并且可以获得请求的结果数据。参数接收一个 回调函数(也被叫做执行器函数用于执行异步操作)
,接收两个参数 resolve
和 reject
,当请求成功
会自动调用 resolve ,失败
则调用 reject。并且会将执行结果返回给 Promise 的实例对象。
一个 Promise
对象代表一个在这个 Promise
被创建出来时不一定已知值的代理。它让你能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
同时 Promise 又有承诺
的意思,意思是,约定好一件事,如果当下不能完成,后续一定会去处理完成,表示暂未完成,未来一定会完成的一种状态。
Promise 的几种状态
一个 Promise 对象拥有 三种状态,在同一时刻必然处于以下几种状态之一:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):意味着操作成功完成。
- 已拒绝(rejected):意味着操作失败。
1.pengding:意思是 待定的,即将要发生的
, 这是 Promise 的初始化状态 ,如果创建 Promise 对象的时候,且没有调用resolve
或者是reject
方法 ,这时候状态就会为 pending
,,这个初始化状态会随着你调用了 resolve
,或者是reject
函数而切换到另一种状态。
待定状态的 Promise 对象要么会通过一个值被兑现,要么会通过一个原因(错误)被拒绝。当这些情况之一发生时,我们用 Promise 的 then 方法排列起来的相关处理程序就会被调用。如果 Promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序也同样会被调用,因此在完成异步操作和绑定处理方法之间不存在竞态条件。
2.fulfilled: 表示成功了解决了,并且兑现了 “承诺”
, 状态已经从 pending
转变成 fulfilled
了,要实现从 pending
到 fulfilled
的转变,需要在创建Promise对象时,在函数体中调用了resolve
方法。
3.rejected: 表示失败了,虽然得到了返回结果,但并不是我想要的,代码拒绝往后执行。要实现从pending
到rejected
的转换,只需要在创建Promise对象时,调用reject
函数。
最后不管是成功还是失败,都会有一个结果,通常我们将成功数据称为 value,失败的数据称为 reason,并且当 Promise 的状态改变后,就不会再变了,是不可逆的。状态的改变伴随着事件的触发,一个 Promise 的状态只能被改变一次。
console.dir(Promise)
浏览器输出 Promise 原型对象,可以看见在它身上有很多属性方法。
Promise 的实例身上都会有 一个 then
方法,如上图,该方法有两个函数作为参数 .then(resolvedFunc, rejectedFunc)
- resolvedFunc 状态
成功
时执行的回调函数 - rejectedFunc 状态
失败
时执行的回调函数
所以说,如果返回的值,依然是一个 Promise ,那么就可以进行 then 方法的 链式调用
。
拆分细解 Promise
Promise 构造函数接收一个 callback 作为参数,这个 callback 被称为回调函数,用于执行异步操作:
let pro = new Promise(() => { })
console.log(pro); // Promise {<pending>} 所有 Promise 初始状态都为 pending
回调函数接收两个参数 resolve, reject
,它们的类型都为 一个 function
let pro = new Promise((resolve, reject) => {
//执行异步任务请求的操作
})
console.log(pro);
异步请求如果,成功就调用 resolve
,失败就调用 reject
。最终的返回数据结果 ,会返回到 实例对象 pro上。
let pro = new Promise((resolve, reject) => {
//执行异步任务请求的操作
// 请求处理成功后调用 resolve(value) 把成功的数据返回出去
//请求处理如果 失败后调用 reject(reason) 把失败的信息也给返回出去
})
console.log(pro);
最后实例对象 pro 身上会有 一个 then
方法,同样可以接收两个回调函数作为参数。一旦在 Promise 函数中 成功调用了 resolve() 将会执行 then
中第一个回调函数,失败则会执行 then
的第二个回调函数:
pro().then(
value => { console.log(value)},
reason => { console.log(reason)}
)
流程图例:
案例
let pro = new Promise((resolve, reject) => {
let a = 10;
setTimeout(() => {
if (a > 5) {
resolve(a)
} else {
reject(a)
}
}, 5000)
})
console.log(pro);
pro.then(
value => { console.log("成功的" + value) },
reason => { console.log("失败的" + reason) }
)
当我们案例中 a 大于5的时候, resolve 方法调用,返回数据, 在 then 方法中第一个 value 回调参数输出成功返回的值。
反之,当我们案例中 a 小于5 的时候, reject 方法调用,返回数据, 在 then 方法中 第二个 reason 回调参数输出失败返回的值。
Promise 实例化 执行流程图例:
使用 catch 替代 then 的第二个回调
虽然 then 方法,可以接收两个参数,用来输出 成功 和 失败
的信息,但是建议 then 方法
只用来输出 成功
的信息,失败的信息可以用 catch()
来输出,这样显得更具语义化以及结构化,更加的清晰。
如:
let pro = new Promise((resolve, reject) => {
let a = 4;
setTimeout(() => {
if (a > 5) {
resolve(a)
} else {
reject(a)
}
}, 5000)
})
console.log(pro);
pro.then(value => {
console.log("成功的" + value)
}).catch(reason => {
console.log("失败的" + reason)
})
需注意一点
: Promise 的那个回调函数,实际上是一个 同步回调函数
,只是当遇到 resolve()
或者 reject()
,时会调用 then
方法,而 then
,方法是属于以前的回调,所以 then
方法中的 回调 是异步回调函数
。如下案例,分析输出的顺序 。
let pm = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
});
console.log(3);
pm.then(() => {
console.log(4);
});
console.log(5);
案例印证了上面的观点。
Promise all()方法
all 方法用来将 多个 Promise
实例包裹成一个新的 Pomise 实例,它接收 一个数组作为参数,数组中,传入 N个 Promise 对象,返回一个新的 Promise。
let p1 = new Promise((resolve, reject) => {
setTimeout(function () {
resolve(1);
}, 1000);
});
let p2 = new Promise((resolve, reject) => {
setTimeout(function () {
resolve(2);
}, 5000);
});
let p3 = new Promise((resolve, reject) => {
setTimeout(function () {
resolve(3);
}, 200);
});
Promise.all([p1, p2, p3])
.then((values) => {
console.log(values); // [1, 2, 3]
})
.catch((reason) => {
console.log(reason);
});
上面案例中,有 3个 Promise 实例对象的回调函数,通过 all 方法,将多个 Promise 进行包裹处理,异步的执行顺序,会按照参数中,所定义的顺序来进行执行。
值得注意
:只有当数组中的 Promise 全部都为成功 状态的时候,才会触发 then
方法,若其中有一个为失败的状态,则就会 直接触发 catch
方法返回失败的信息,不会触发,then
方法。
then()方法 返回一个新的 Promise 时的状态由什么决定?
返回的新的 Promise 的状态,主要是根据 前一个 Promise 对象的返回值来决定的。
大致分为以下几种状态情况。
- 若抛出异常,新 Promise 状态变为 rejected,reason 为抛出的异常原因
- 若返回非 Promise 的值,新 promise 状态变为 resolved,value 为返回的值
- 若返回新的 Promise 结果就成为新 promise 的结果
总结
以上就是给大家 带来的 ES6 中 Promise 的概念用法,如今越来越多的封装框架化,确实带来了很多的便利,但是也不要忘记了掌握很多的原生的语法逻辑,有时候,回过头来,再看一看原生的东西,又是另一番感觉和领悟!
🚵♂️ 博主座右铭:向阳而生,我还在路上!
——————————————————————————————
🚴博主想说:将持续性为社区输出自己的资源,同时也见证自己的进步!
——————————————————————————————
🤼♂️ 如果都看到这了,博主希望留下你的足迹!【📂收藏!👍点赞!✍️评论!】
——————————————————————————————