任何符合promise规范的对象和函数都可以成为Promise。
以下内容参考自promise A plus 规范,地址:https://promisesaplus.com/
基本术语
- Promise:是一个具有then方法的对象或函数,其行为符合Promises/A+规范。
- thenadble:是一个定义了then方法的对象或函数。
- value:指任何JavaScript的合法值(包括undefined,thenable,和promise)。
- exception:使用throw抛出的一个值。
- 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