参考:www.jianshu.com/p/8a367df8e…
Promise 核心知识点
描述promise框架 - 规范
-
- promise有哪些状态?
pending、fulfilled、rejected
- promise有哪些状态?
-
- new Promise 执行器executor(),执行器参数是? -
resolve、reject
- new Promise 执行器executor(),执行器参数是? -
-
- promise的默认状态是?promise状态的流转? - 默认
pendingpending-->fulfilledpending-->rejected
- promise的默认状态是?promise状态的流转? - 默认
-
- promise,value保存成功状态的枚举?-
undefinedthenablepromise
- promise,value保存成功状态的枚举?-
-
- promise,失败状态值?- reason保存失败 描述promise接口
-
- promise一定会有then,then接收来源? - 两个回调
onFulfilled(value)+onRejected(reason)
- promise一定会有then,then接收来源? - 两个回调
executor 与三个状态
new Promise时,需要传递一个executor执行器函数,在构造函数中,执行器函数立刻执行executor执行函数接受两个参数,分别是resolve和rejectPromise只能从pending到rejected, 或者从pending到fulfilledPromise的状态一旦确认,状态就凝固了,不在改变
then 方法
- 所有的
Promise都有then方法,then接收两个参数,分别是Promise成功的回调onFulfilled,和失败的回调onRejected - 如果调用
then时,Promise已经成功,则执行onFulfilled,并将Promise的值作为参数传递进去;如果Promise已经失败,那么执行onRejected,并将Promise失败的原因作为参数传递进去;如果Promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(观察者模式) then的参数onFulfilled和onRejected可以不传,Promise可以进行值穿透。
链式调用并处理 then 返回值
Promise可以then多次,Promise的then方法返回一个新的Promise。- 如果
then返回的是一个正常值,那么就会把这个结果(value)作为参数,传递给下一个then的成功的回调(onFulfilled) - 如果
then中抛出了异常,那么就会把这个异常(reason)作为参数,传递给下一个then的失败的回调(onRejected) - 如果
then返回的是一个promise或者其他thenable对象,那么需要等这个promise执行完撑,promise如果成功,就走下一个then的成功回调;如果失败,就走下一个then的失败回调。
手写promise - 同步版本
// pending -> resolve方法 -> fulfilled
// pending -> reject方法 -> rejected
// 三个状态:PENDING FULFILLED REJECTED
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class Promise { //类
constructor(executor){ //构造
this.status = PENDING
this.value = undefined
this.reason = undefined
let resolve = value =>{
if(this.status === PENDING){
this.status = FULFILLED
this.value =value
}
}
let reject = reason =>{
if(this.status === PENDING){
this.status = REJECTED
this.reason =reason
}
}
try{
executor(resolve,reject) //executor 接受上面的两个resolve和reject函数去执行你写入的resolve或reject方法
}catch(error){
reject(error)
}
}
then(onFulfiled,onRejected) { // then 接收你写入的callback函数,将你改写的this.value或者this.reason返回出去
if(this.status === FULFILLED){
onFulfiled(this.value)
}
if(this.status === REJECTED){
onRejected(this.reason)
}
}
}
const promise = new Promise((resolve,reject)=>{
resolve('successs')
// reject('failed')
}).then(
data=>{console.log('data---->',data)},
err=>{console.log('err---->',err)}
)
promise --异步版本
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class MyPromise {
constructor(executor) {
this.status = PENDING;
this.value = undefined; // 用于保存 resolve 的值
this.reason = undefined; // 用于保存 reject 的值
this.resolvedQueues = []; // 用于保存 then 的成功回调数组
this.rejectedQueues = []; // 用于保存 then 的失败回调数组
let resolve = value => {
// 同时遍历执行 成功回调数组中的函数,将 value 传入
if (this.status == PENDING) {
this.value = value;
this.status = FULFILLED;
this.resolvedQueues.forEach(fn => fn())
}
}
let reject = reason => {
// 同时遍历执行 失败回调数组中的函数,将 reason 传入
if (this.status == PENDING) {
this.reason = reason;
this.status = REJECTED;
this.rejectedQueues.forEach(fn => fn())
}
}
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// 定义onFulfilled ,onRejected两参数,是因为防止在p1.then()未传入参数报错
onFulfilled =
typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected =
typeof onRejected === 'function' ? onRejected : reason => { throw reason }
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onRejected(this.reason)
}
if (this.status === PENDING) {
this.resolvedQueues.push(()=>{
onFulfilled(this.value)
})
this.rejectedQueues.push(()=>{
onRejected(this.reason)
})
}
return this;
}
}
let p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功了');
}, 1000);
})
p1.then((res) => {console.log('结果:',res)})
// p1.then().then((res) => { console.log('结果:',res)})
解释下在异步中为什么要用到resolvedQueues和rejectedQueues这两个数组
执行步骤:
- 第一步:new MyPromiseh后执行constructor函数,传入的executor就是我们写的
(resolve, reject) => { setTimeout(()=>{ resolve('成功了'); },1000)
- 第二步:在try{executor(resolve, reject)}执行中,因为executor里面是个setTimeout函数 ,resolve被包裹在里面并没用立即执行,所以执行到then函数时,this.status并没有改变,还是pending状态,then就会将你写入的函数push到数组里
(res) => { console.log('结果:',res); } // 你写入的函数
- 第三步: 当setTimeOut到时间后开始执行了,这时候触发了resolve函数将this.statu改成
FULFILLED状态,将this.value改成成功了,这时候遍历resolvedQueues数组里的各函数,执行之前存入的函数
fn()
等同于
(this.value) => { console.log('结果:',this.value) } //this.value === '成功了'