什么是Promise
Promise对象是JavaScript异步操作解决方案,为异步操作提供统一接口。Promise可以让异步操作写起来,就像在写同步操作的流程,而不必一层层的嵌套回调函数。就是我们所说的回调地狱。
怎么实现一个Promise?
第一部分
实现之前我们先了解下它的一些特点,结合这些特点我们实现起来会比较容易理解一点。
- 有三种状态,默认是pending,成功为fulfilled,失败为rejected
- 创建时必须传递一个函数,不然会报错
- 传递函数中参数是两个回调函数,resolve和reject
- 状态一旦发生改变就不会发生变化
特点很多我们先按照这些特点慢慢实现
class MyPromise{
constructor(fn) {
// 2:promise接收的必须是个函数,不然报错
if (!this.isFunc(fn)){
throw new Error('这不是个函数')
}
// 1:定义默认状态
this.status = 'pending'
//3:函数参数中有两个回调参数;resolve和reject
this.resolve = (data) =>{
//状态一旦发生改变就不会在改变,所以在这里判断下是否为默认状态
if (this.status === 'pending'){
this.status = 'fulfilled'
}
}
this.reject = (data) =>{
if (this.status === 'pending'){
this.status = 'rejected'
}
}
fn(this.resolve,this.reject)
}
// 首先定义个方法判断是否为函数
isFunc(fn){
return typeof fn === 'function'
}
}
let a = new MyPromise(function (resolve,reject){
resolve()
console.log('执行了');
})
console.log(a);
看下执行结果,状态已经是成功了
第二部分
再说说还有的特点
- 同一个promise对象可以添加多个then监听,状态改变时会按照监听顺序依次执行
- then方法每次执行完毕会返回一个新的promise对象
- 上一个Promise对象的then方法可以给返回的新的Promise的then传递参数
- 无论上一个是在then成功或者失败的回调中传参,都会传递给新的Promise对象then方法中成功的回调
- 如果上一个传递的是一个Promise对象,那么传给下一个的成功还是失败由传递的Promsie状态决定
代码块有点问题,放个图片
看下运行结果:
这里难理解的可能就是对then return的值进行判断,因为下个promise会继承上一个promise的状态,因为如果then中return的是一个promise对象的话,下一个promise的状态就是按照这个return过来的。
第三部分
最后一点了。也是上面的基础上的补充
-
then返回的promise可以捕捉当前then方法中的异常
-
catch方法就是then方法的语法糖
多余的注释我就先去掉了,下面就是完整版的了
class MyPromise{
constructor(fn) {
if (!this.isFunc(fn)){
throw new Error('这不是个函数')
}
this.status = 'pending'
//定义两个属性保存resolve和reject中的参数
this.value = undefined
// 存放成功的数组
this.onSuccessCallbacks = []
this.fail = undefined
// 存放失败的数组
this.onFailCallbacks = []
//函数参数中有两个回调参数;resolve和reject
this.resolve = (data) =>{
//状态一旦发生改变就不会在改变,所以在这里判断下是否为默认状态
if (this.status === 'pending'){
this.status = 'fulfilled'
this.value = data
if (this.onSuccessCallbacks){
this.onSuccessCallbacks.forEach((fn) => {
fn(this.value)
})
}
}
}
this.reject = (data) =>{
if (this.status === 'pending'){
this.status = 'rejected'
this.fail = data
if (this.onFailCallbacks){
this.onFailCallbacks.forEach((fn) => {
fn(this.fail)
})
}
}
}
fn(this.resolve,this.reject)
}
then(onSuccess,onFail){
return new MyPromise((nextSuccess,nextFail) => {
//then返回的promise可以捕捉当前then方法中的异常
// 所以我们可以利用try catch来捕获异常
try {
if (this.isFunc(onSuccess)){
if (this.status === 'fulfilled'){
let res = onSuccess(this.value)
if (res instanceof MyPromise){
res.then(nextSuccess,nextFail)
}else if (res !== undefined){
nextSuccess(res)
}else {
nextSuccess()
}
}
}
// 将异常信息传递给下一个promise失败的回调
}catch (e) {
nextFail(e)
}
try {
if (this.isFunc(onFail)){
if (this.status === 'rejected'){
let res = onFail(this.fail)
if (res instanceof MyPromise){
res.then(nextSuccess,nextFail)
}else if (res !== undefined){
nextSuccess(res)
}else {
nextFail()
}
}
//这里要加个判断,因为我们有时写的话可能会省略then中失败的回调,利用catch捕获
}else if (onFail === undefined){
if (this.fail){
nextFail(this.fail)
}
}
}catch (e) {
nextFail(e)
}
// 解决延迟回调的问题
if (this.status === "pending"){
if (this.isFunc(onSuccess)){
this.onSuccessCallbacks.push(() => {
try {
let res = onSuccess(this.value)
if (res instanceof MyPromise){
res.then(nextSuccess,nextFail)
}else if (res !== undefined){
nextSuccess(res)
}else {
nextSuccess()
}
}catch (e) {
nextFail(e)
}
})
}
if (this.isFunc(onFail)){
this.onFailCallbacks.push(() => {
try {
let res = onFail(this.fail)
if (res instanceof MyPromise){
res.then(nextSuccess,nextFail)
}else if (res !== undefined){
nextSuccess(res)
}else {
nextFail()
}
}catch (e) {
nextFail(e)
}
})
}else if (onFail === undefined){
this.onFailCallbacks.push(nextFail)
}
}
})
}
// catch可以看作是then的一个语法糖
catch(onFail){
return this.then(undefined , onFail)
}
// 首先定义个方法判断是否为函数
isFunc(fn){
return typeof fn === 'function'
}
}
let a = new MyPromise(function (resolve,reject){
resolve('xyz')
// reject('xyz')
console.log('执行了');
})
let b = a.then(function (data) {
console.log(data,'成功');
xxx
})
b.then(function (data) {
console.log(data);
},function (data) {
console.log(data,'sss');
})
看下执行结果
这里下一个promise成功捕捉到了上一个then中的错误
Promise的其他方法
all方法
Promise的all方法接收一个数组,数组中存放promise对象,只有数组中的promise都成功了才会执行then方法,并且会按照添加的顺序,将所有成功的结果重新打包到一个数组中返回给我们,如果有一个失败就会立即执行失败的回调。
要么一起成功,要么一起失败
//因为all是一个静态方法
static all(list){
//因为返回的是一个数组,所以先定义一个
let arr = []
return new MyPromise((resolve,reject) => {
list.forEach((value) => {
value.then((data) => {
arr.push(data)
},(error) =>{
reject(error)
})
})
resolve(arr)
})
}
race方法
Promise的race方法接收一个数组,数组中存放promise对象。不过它取决于数组中第一个promise的状态
// race 也是个静态方法
static race(list){
return new MyPromise((resolve,reject)=>{
list.forEach((value) => {
value.then(function (data) {
resolve(data)
},function (error) {
reject(error)
})
})
})
}
总结
我表达的可能不是太好,不太容易理解,也可能有错误的地方我没检查出来。希望大家多多包含?
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!