Promise详解二(解读Promise规范 + 一些小测试)

任何符合promise规范的对象和函数都可以成为Promise。
以下内容参考自promise A plus 规范,地址:https://promisesaplus.com/

基本术语

  1. Promise:是一个具有then方法的对象或函数,其行为符合Promises/A+规范。
  2. thenadble:是一个定义了then方法的对象或函数。
  3. value:指任何JavaScript的合法值(包括undefined,thenable,和promise)。
  4. exception:使用throw抛出的一个值。
  5. reason:说明Promise状态改为rejected的原因。

要求

1. Promise的状态

一个Promise的当前状态必须是一下三种状态中的一种:pending,fullfilled,rejected。

  • 当处于pending状态时,Promise可以转换为fullfilled状态或rejected状态。
  • 当处于fullilled状态时,Promise的状态不能被更改,且必须有一个不可变的值。
  • 当处于rejected状态时,Promise的状态不能被更改,且必须有一个不可变的原因。

2. then方法

Promise必须提供一个then方法,可以查看其当前或最终的值或者原因。
Promise的then方法接收两个可选参数:Promise.then(onFullfilled, onRejected)。

2.1 如果onFullfilled或onRejected不是函数,则需要忽略他们。
2.2 如果onFullfilled是一个函数:

  • Promise的状态变为fullfilled前其不能被调用。
  • Promise的状态变为fullfilled后必须被调用,且接收Promise的结果作为第一个参数。
    最多被调用一次。

2.3 如果onRejected是一个函数:

  • Promise的状态变为rejected前其不能被调用。
  • Promise的状态变为rejected状态后必须被调用,且接收Promise的原因作为第一个参数。
    最多被调用一次。

2.4 当执行上下文堆栈仅包含“platform code”之前,不能调用onFullFilled和onRejected。

这里“platform code”是指引擎、环境和Promise参数函数代码。在实际应用中,这一要求确保onFulfilled和onRejected在调用事件循环后以新的堆栈异步执行。这可以通过“宏任务”机制(如setTimeout或setImmediate)实现,也可以通过“微任务”机制(如MutationObserver或process.nextTick实现。

2.5 onFulfilled 和 onRejected 必须被作为普通函数调⽤(即⾮实例化调⽤,这样函数内部 this ⾮严格模式下指向 window)。
2.6 then ⽅法可以被同⼀个 promise 调⽤多次。

  • 当 promise 成功执⾏时,所有 onFulfilled 需按照其注册顺序依次回调。
  • 当 promise 被拒绝执⾏时,所有的 onRejected 需按照其注册顺序依次回调。

2.7 then ⽅法必须返回⼀个新的 promise 对象: promise2 = promise1.then(onFulfilled, onRejected);

  • 只要 onFulfilled 或者 onRejected 返回⼀个值 x ,promise2 都会进⼊ resolved 状态。
  • 如果 onFulfilled 或者 onRejected 抛出⼀个异常 e ,则 promise2 会进入rejected状态,并返回拒绝原因 e。
  • 如果 onFulfilled 不是函数且 promise1 状态变为fullfilled, promise2 会进入fullfilled状态并返回相同的值。
  • 如果 onRejected 不是函数且 promise1 状态变为rejected, promise2 会进入rejected状态并返回相同的拒绝原因。

3. Promise的解析过程

promise解析过程是一个抽象操作,输入一个promise和一个值,我们将其表示为[[Resolve]](promise,x)。如果x是一个tenable,它试图使promise采用x的状态。否则,它就将x值包装成一个Promise。
3.1 如果promise和x指向同一个对象,Promise将进入rejected状态,并返回一个TypeError作为拒绝原因。
3.2 如果 x 为 promise:

  • 如果 x 处于pending状态, promise 需保持为pending直⾄ x 被执⾏或拒绝。
  • 如果 x 处于fullfilled状态,⽤相同的值执⾏ promise。
  • 如果 x 处于rejected态,⽤相同的拒绝原因拒绝promise。

3.3 如果 x 为对象或函数(不常见):

  • 首先尝试执行x.then,
  • 如果取x.then时抛出错误e,则以e为原因拒绝Promise。
  • 如果then是函数,将x作为函数作用域调用。传递两个回调函数作为参数,第一个叫做resolvePromise,第二个叫做rejectPromise:
    • 如果 resolvePromise 以值 y 为参数被调⽤,则运⾏[[Resolve]](promise,y)。
    • 如果 rejectPromise 以拒绝原因 r 为参数被调⽤,则以拒绝原因 r 拒绝 promise。
    • 如果 resolvePromise 和 rejectPromise 均被调⽤,或者被同⼀参数调⽤了多次,则优先采⽤⾸次调⽤并忽略其他的调⽤。
    • 如果调⽤ then ⽅法抛出了异常 e:
      • 如果 resolvePromise 或 rejectPromise 已经被调⽤,则忽略。
      • 否则以 e 为拒绝原因拒绝 promise。
    • 如果then不是函数,以x为参数将Promise变为fullfilled状态。

3.4 如果 x 不是对象或者函数,以x为参数将Promise变为fullfilled状态(重要且常见)。

------------------------------------------------------------一些测试示例---------------------------------------------------------------

// 示例1
new Promise((resolve, reject) => {
  resolve('test')
}).then((res) => {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
          resolve(new Promise((res, rej) => {
              rej(new Promise((res1, rej1) => {
                  rej('abc');
              }));
          }));
      }, 0);
  });
}).then((res) => {
  console.log(res);
}, (err) => {
  console.error(err)
})
// Promise {<rejected> 'abc'}

// 示例2
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Promise((res, rej) => {
                rej(new Promise((res1, rej1) => {
                    rej1('abc');
                }));
            }));
        }, 0);
    })
}).then((res) => {
    console.log(res);
}, (err) => {
    console.error(err);
})
// Promise { <rejected> Promise {<rejected> 'abc'} }

// 示例3
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((res, rej) => {
                resolve('test1');
            }).then(() => {
                return {
                    then: 'test2'
                }
            }));
        }, 0);
    })
}).then((res) => {
    console.log(res);
}, (err) => {
    console.error(err);
})
// test1

// 示例4
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((res, rej) => {
                res('test1');
            }).then(() => {
                return {
                    then: 'test2'
                }
            }));
        }, 0);
    })
}).then((res) => {
    console.log(res);
}, (err) => {
    console.error(err);
})
// { then: 'test2' }

// 示例5
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((res, rej) => {
                res('test1');
            }).then(() => {
                return {
                    aaa: 'test2'
                }
            }));
        }, 0);
    })
}).then((res) => {
    console.log(res);
}, (err) => {
    console.error(err);
})
// {aaa: 'test2'}

// 示例6
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((res, rej) => {
                res('test1');
            }).then(() => {
                return {
                  // then: 'test2'
                    then: () => {
                        return 'test2'
                    }
                }
            }));
        }, 0);
    })
}).then((res) => {
    console.log(res)
}, (err) => {
    console.error(err);
})
// 没有打印

// 示例7
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((res, rej) => {
                res('test1');
            }).then(() => {
                return {
                    then: (res1) => {
                        res1('test2');
                    }
                }
            }));
        }, 0)
    })
}).then((res) => {
    console.log(res);
}, (err) => {
    console.error(err);
})
// test2 

// 示例8
new Promise((resolve, reject) => {
    resolve('test');
}).then((res) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((res, rej) => {
                res('test1');
            }).then(() => {
                return {
                    then: (res1, rej1) => {
                        rej1('test2');
                    }
                }
            }));
        }, 0);
    })
}).then((res) => {
    console.log(res);
}, (err) => {
    console.error(err);
})
// test2
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值