本文分为两部分,第一部分为Promise内容及方法的一些介绍,第二部分为自定义Promise
Promise
不想看这部分的话,可以直接定位到自定义Promise部分哦
内容
Promise是js中进行异步编程的解决方案
语法上:Promise是一个构造函数
功能上:Promise对象用来封装一个异步操作并可以获得其结果
状态
三种状态pending、resolved、rejected
pending -> resolved (成功)
pending -> rejected(失败)
状态只能改变一次,且不可逆
无论成功失败,都会有一个结果数据value or reason
流程

为什么引入Promise
- 指定回调函数的方式更加灵活
传统回调函数,在调用异步操作之前,就得先指定回调函数
const success = () => {}
const fail = () => {}
createAsyncFun(data, success, fail)
promise: 启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束之后指定)
- 支持链式调用,可以解决回到地狱问题
方法
1. Promise构造函数:Promise(excutor) {}
excutor函数:同步执行(resolve, reject) -> {}
resolve函数:内部定义成功时调用的函数 value => {}
reject函数:内部定义失败时调用的函数 reason => {}
2. Promise.prototype.then()方法: (onResolved, onRejected) => {}
onResolved函数:成功的回调函数 value => {}
onRejected函数:失败的回调函数 reason => {}
说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的promise对象
3. Promise.prototype.catch():(onRejected) => {}
onRejected函数:失败的回调函数 reason => {}
说明:then()的语法糖,相当于then(undefined, onRejected)
4. Promise.resolve方法:value => {}
value:成功的数据或promise对象
说明:返回一个成功/失败的promise对象
5. Promise。reject方法:reason => {}
reason:失败的原因
说明:返回一个失败的promise对象
6. Promise.all方法:promises => {}
promises:包含n个promise的数据
说明:有一个失败就失败
7. Promise.race方法:promises => {}
promises:包含n个promise的数据
说明:以第一个执行完成的结果为结果(看谁执行的快)
等等
说明
Promise.prototype.then()、Promise.prototype.catch()
由实例对象调用,所以是挂在 原型对象 上的
Promise.resolve()、Promise.reject()、Promise.all()、Promise.race()
挂在 函数对象 上
如何改变promise的状态
- resolve(value) :如果当前是pending就会变为resolved
- reject(value) :如果当前是pending就会变为rejected
- 抛出异常:如果当前是pending就会变为rejected,抛出的是啥,reason就是啥
一个promise指定多个成功/失败回调函数,当promise改变为对应状态时都会调用
改变promse状态和指定回调函数谁先谁后?
- 都有可能,正常情况下时先指定回调函数再改变状态,但也可以先改状态再指定回调
- 如何先改状态再指定回调
① 在执行器中直接调用resolve()/reject()
② 延迟更长时间调用then() - 什么时候才能得到数据?
① 如何先指定的回调,那当状态发生变化时,回调函数就会调用,得到数据
② 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
// 先改状态,再指定回调
new Promise((resolve, reject) => {
resolve(1) // 先改变状态
}).then(
value => { console.log(value) }, // 再指定回调
reson => {}
)
const p = new Promise((resolve, reject) => {
setTimeout(() => { // 先改变状态
resolve(1)
}, 1000)
})
setTimeout(() => {
p.then(
value => { console.log(value) }, // 再指定回调
reson => {}
)
}, 1100)
// 先指定回调,再改变状态
new Promise((resolve, reject) => {
setTimeout(() => { // 后改变状态
resolve(1)
}, 1000)
}).then(
value => { console.log(value) }, // 先指定回调
reson => {}
)
promise.then()返回的新promise的结果状态由什么决定?
- 简单表达:由then()指定的回调函数执行的结果决定
- 详细表达:
① 如果抛出异常,新promise变为rejected,reason为抛出的异常
② 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
③ 如果返回的是另一个promise,此promise的结果就会成为新promise的结果
promise异常传/穿透
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 前面任何操作出了异常,都会传到最后失败的回调中处理
new Promise((resolve, reject) => {
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
}
).catch(
value => {
console.log('onRejected2()', value)
}
).then(
value => {
console.log('onResolved2()', value)
}
)
// 执行结果:
// onRejected2() 1
// onResolved2() undefined
// new Promise执行失败,执行onRejected(),但是onRejected()没有指定回调
// 相当于执行 reason => { throw reson } 或 reson => { return Promise.reject(reason) }
中断promise链
- 当使用promise的then链式调用时,在中间中断,不能调用后面的回调函数
- 办法:在回调函数中返回一个pending状态的promise对象
new Promise((resolve, reject) => {
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
},
reason => {
throw reason
}
).catch(
value => {
console.log('onRejected2()', value)
return new Promise(() => {}) // 返回一个pending状态的promise链
}
).then(
value => {
console.log('onResolved2()', value)
}
)
// onRejected2() 1
咔咔 内容终于介绍完了,现在开始实现自定义Promise
自定义Promise
Promsie基础用法
new Promise((resolve, reject) => {
if (成功) {
resolve(数据)
} else {
reject(数据)
}
})
.then(
value => {},
reason => {}
)
先写构造函数
promise.js
// 接收一个执行器函数(同步执行)的参数
function Promise(excutor) {
// 执行器函数接收两个参数(resolve, reject)
// 立即同步执行执行器函数
excutor(resolve, reject)
}
定义执行器的参数resolve、reject
定义存储状态的变量status
定义存储值的变量data
定义存储回调函数的数据callbacks (数组每个元素是json结构 {onFulfilled(){}, onRejected() {}})
function Promise(excutor) {
this.status = 'pending'; // 给promise对象指定status属性,初始值为pending
this.data = null; // 给promise对象指定一个用于存储结果数据的属性
this.callbacks = []; // 每个元素的结构: {onFulfilled() {}, onRejected() {}}
const resolve = (value) => {}
const reject = (reason) => {}
excutor(resolve, reject)
}
完善resolve
function Promise(excutor) {
this.status = 'pending'; // 给promise对象指定status属性,初始值为pending
this.data = null; // 给promise对象指定一个用于存储结果数据的属性
this.callbacks = []; // 每个元素的结构: {onFulfilled() {}, onRejected() {}}
const resolve = (value) => {
// 状态只能改变一次,判断不是pending,就直接结束
if (this.status !== 'pending') return;
// 将状态改为resolved
this.status = 'resolved';
// 保存value数据
this.data = value;
// 如果有待执行的callback函数,立即异步执行回调函数onFulfilled
if (this.callbacks.length > 0) {
setTimeout(() => {
this.callbacks.forEach(callbacksObj => {
callbacksObj.onFulfilled(value)
})
})
}
}
const reject = (reason) => {
}
excutor(resolve, reject)
}
reject与resolve类似
function Promise(excutor) {
this.status = 'pending'; // 给promise对象指定status属性,初始值为pending
this.data = null; // 给promise对象指定一个用于存储结果数据的属性
this.callbacks = []; // 每个元素的结构: {onFulfilled() {}, onRejected() {}}
const resolve = (value) => {
// 状态只能改变一次,判断不是pending,就直接结束
if (this.status !== 'pending') return;
// 将状态改为resolved
this.status = 'resolved';
// 保存value数据
this.data = value;
// 如果有待执行的callback函数,立即异步执行回调函数onFulfilled
if (this.callbacks.length > 0) {
setTimeout(() => {
this.callbacks.forEach(callbacksObj => {
callbacksObj.onFulfilled(value)
})
})
}
}
// reject与resolve类似
const reject = (reason) => {
// 状态只能改变一次,判断不是pending,就直接结束
if (this.status !== 'pending') return;
// 将状态改为rejected
this.status = 'rejected';
// 保存reason数据
this.data = reason;
// 如果有待执行的callback函数,立即异步执行回调函数onRejected
if (this.callbacks.length > 0) {
setTimeout(() => { // 放入队列中执行所有成功的回调
this.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason)
})
})
}
}
// 如果执行器抛异常,promise变为失败的状态
try{
excutor(resolve, reject)
} catch(e) {
reject(e)
}
}
Promise构造函数就写好了
then()方法
then()是挂在实例对象上的,并且接收两个参数,onFulfilled, onRejected
then()返回一个promise对象
Promise.prototype.then = (onFulfilled, onRejected) => {
let promise2 = new Promise((resolve, reject) => {
})
return promise2;
}
判断状态
Promise.prototype.then = (onFulfilled, onRejected) => {
let promise2 = new Promise((resolve, reject) => {
if (this.status = 'resolved'){
}
else if (this.status = 'rejected') {
}
else if (this.status = 'pending') {
}
})
return promise2;
}
status为resolved/rejected时,说明先改变状态,再执行的回调,此时应立即执行回调
status为pending时,此时还未改变状态,说明是先指定回调函数,再改变状态,所以要把回调函数存储起来
Promise.prototype.then = (onFulfilled, onRejected) => {
let promise2 = new Promise((resolve, reject) => {
if (this.status = 'resolved'){
setTimeout(() => {
try{
// 执行成功的回调onFulfilled
let x = onFulfilled(this.data);
// 2.2.7.1 onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
resolvePromise(promise2, x, resolve, reject)
} catch(e){
reject(e)
}
})
}
else if (this.status = 'rejected') {
setTimeout(() => {
try{
// 执行失败的回调onRejected
let x = onRejected(this.data);
// 2.2.7.1 onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
resolvePromise(promise2, x, resolve, reject)
} catch(e){
reject(e)
}
})
}
else if (this.status = 'pending') {
// 此时还未改变状态,说明是先指定回调函数,再改变状态,所以要吧回调函数存储起来
// callbacks数组每一项元素是一个json
// 如果返回的结果是promise类型,那return的promise的结果就是返回的promise对象的结果
// 所以这个要获取到promise执行的结果
this.callbacks.push({
onFulfilled: onFulfilled() {
try{
let x = onFulfilled(this.data);
resolvePromise(promise2, x, resolve, reject)
} catch(e){
reject(e)
}
},
onRejected: onRejected() {
try{
let x = onRejected(this.data);
resolvePromise(promise2, x, resolve, reject)
} catch(e){
reject(e)
}
}
})
}
})
return promise2;
}
规范2.2.1.1 onFulfilled 必须是函数类型
规范2.2.1.2 onRejected 必须是函数类型
then()方法第一行添加以下代码
// 指定回调函数的默认值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; // 向后传递成功的value
// 指定失败回调(实现异常传透的关键点)
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason} // 向后传递失败的reason
重复的部分封装为handle
Promise.prototype.then = function(onFulfilled, onRejected) {
// 指定回调函数的默认值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value // 向后传递成功的value
// 指定失败回调(实现异常传透的关键点)
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason} // 向后传递失败的reason
let promise2 = new Promise((resolve, reject) => {
const handle = (callback) => {
/*
如果抛出异常,那return的promise就失败,reason就是error
*/
try {
// 执行失败的回调onRejected
let x = callback(this.data);
// 2.2.7.1 onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}
if (this.status === 'pending') { // 说明先指定回调,再改变状态,此时存储回调函数
this.callbacks.push({
onFulfilled () {
handle(onFulfilled)
},
onRejected () {
handle(onRejected)
}
})
} else if (this.status === 'resolved') { // 说明先改变状态,再执行回调,此时立即执行回调
setTimeout(() => {
handle(onFulfilled)
})
} else { // 'rejected'
setTimeout(() => {
handle(onRejected)
})
}
})
return promise2;
}
Promise/A+规范(部分)
2.3 resolvePromise
resolvePromise(promise2, x, resolve, reject)
2.3.1 如果 promise2 和 x 相等,那么 reject promise with a TypeError
2.3.2 如果 x 是一个 promsie
2.3.2.1 如果x是pending态,那么promise必须要在pending,直到 x 变成 fulfilled or rejected.
2.3.2.2 如果 x 被 fulfilled, fulfill promise with the same value.
2.3.2.3 如果 x 被 rejected, reject promise with the same reason.
2.3.3 如果 x 是一个 object 或者 是一个 function
2.3.3.1 let then = x.then.
2.3.3.2 如果 x.then 这步出错,那么 reject promise with e as the reason..
2.3.3.3 如果 then 是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
2.3.3.3.1 resolvePromiseFn 的 入参是 y, 执行 resolvePromise(promise2, y, resolve, reject);
2.3.3.3.2 rejectPromise 的 入参是 r, reject promise with r.
2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都调用了,那么第一个调用优先,后面的调用忽略。
2.3.3.3.4 如果调用then抛出异常e
2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,那么忽略
2.3.3.3.4.3 否则,reject promise with e as the reason
2.3.3.4 如果 then 不是一个function. fulfill promise with x.
2.3.4 如果 x 不是一个 object 或者 function,fulfill promise with x.
resolvePromise实现
function resolvePromise(promise2, x, resolve, reject) {
// 2.3.1 如果 promise2 和 x 相等,那么 reject promise with a TypeError
if (promise2 === x) {
reject(new TypeError('循环引用'))
}
// 2.3.3 如果 x 是一个 object 或者 是一个 function
if (x && typeof x === 'object' || typeof x === 'function') {
// 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都调用了,那么第一个调用优先,后面的调用忽略。
// used保证只执行一次
let used = false;
// 2.3.3.1 let then = x.then.
try{
let then = x.then
// 2.3.3.3 如果 then 是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
if (typeof then === 'function') {
then.call(x,
y => {
if (used) return;
used = true;
resolvePromise(promise2, y, resolve, reject)
},
r => {
if (used) return;
used = true;
reject(r)
}
)
} else {
// 2.3.3.4 如果 then 不是一个function. fulfill promise with x.
if (used) return;
used = true;
resolve(x)
}
} catch(e){
// 2.3.3.2 如果 x.then 这步出错,那么 reject promise with e as the reason..
if (used) return;
used = true;
reject(e)
}
} else {
// 2.3.4 如果 x 不是一个 object 或者 function,fulfill promise with x.
resolve(x)
}
}
resolvePromise()方法完成
catch()方法
catch()是then()方法的语法糖
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected)
}
完整代码
function Promise(excutor) {
this.status = 'pending'; // 给promise对象指定status属性,初始值为pending
this.data = null; // 给promise对象指定一个用于存储结果数据的属性
this.callbacks = []; // 每个元素的结构: {onFulfilled() {}, onRejected() {}}
const resolve = (value) => {
// 状态只能改变一次,判断不是pending,就直接结束
if (this.status !== 'pending') return;
// 将状态改为resolved
this.status = 'resolved';
// 保存value数据
this.data = value;
// 如果有待执行的callback函数,立即异步执行回调函数onFulfilled
if (this.callbacks.length > 0) {
setTimeout(() => {
this.callbacks.forEach(callbacksObj => {
callbacksObj.onFulfilled(value)
})
})
}
}
// reject与resolve类似
const reject = (reason) => {
// 状态只能改变一次,判断不是pending,就直接结束
if (this.status !== 'pending') return;
// 将状态改为rejected
this.status = 'rejected';
// 保存reason数据
this.data = reason;
// 如果有待执行的callback函数,立即异步执行回调函数onRejected
if (this.callbacks.length > 0) {
setTimeout(() => { // 放入队列中执行所有成功的回调
this.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason)
})
})
}
}
// 如果执行器抛异常,promise变为失败的状态
try{
excutor(resolve, reject)
} catch(e) {
reject(e)
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
// 指定回调函数的默认值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value // 向后传递成功的value
// 指定失败回调(实现异常传透的关键点)
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason} // 向后传递失败的reason
let promise2 = new Promise((resolve, reject) => {
const handle = (callback) => {
/*
1. 如果抛出异常,那return的promise就失败,reason就是error
2. 如果返回的结果不是promise类型,那return的promise就成功,value就是返回的结果
3. 如果返回的结果是promise类型,那return的promise的结果就是返回的promise对象的结果
*/
try {
// 执行失败的回调onRejected
let x = callback(this.data);
// 2.2.7.1 onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}
if (this.status === 'pending') { // 说明先指定回调,再改变状态,此时存储回调函数
this.callbacks.push({
onFulfilled () {
handle(onFulfilled)
},
onRejected () {
handle(onRejected)
}
})
} else if (this.status === 'resolved') { // 说明先改变状态,再执行回调,此时立即执行回调
setTimeout(() => {
handle(onFulfilled)
})
} else { // 'rejected'
setTimeout(() => {
handle(onRejected)
})
}
})
return promise2;
}
function resolvePromise(promise2, x, resolve, reject) {
// 2.3.1 如果 promise2 和 x 相等,那么 reject promise with a TypeError
if (promise2 === x) {
reject(new TypeError('循环引用'))
}
// 2.3.3 如果 x 是一个 object 或者 是一个 function
if (x && typeof x === 'object' || typeof x === 'function') {
let used = false; // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都调用了,那么第一个调用优先,后面的调用忽略。
// 2.3.3.1 let then = x.then.
// 2.3.3.2 如果 x.then 这步出错,那么 reject promise with e as the reason..
try{
let then = x.then
// 2.3.3.3 如果 then 是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
if (typeof then === 'function') {
then.call(x,
y => {
if (used) return;
used = true;
resolvePromise(promise2, y, resolve, reject)
},
r => {
if (used) return;
used = true;
reject(r)
}
)
} else {
// 2.3.3.4 如果 then 不是一个function. fulfill promise with x.
if (used) return;
used = true;
resolve(x)
}
} catch(e){
if (used) return;
used = true;
reject(e)
}
} else {
// 2.3.4 如果 x 不是一个 object 或者 function,fulfill promise with x.
resolve(x)
}
}
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected)
}
脚本测试
测试promise是否符合Promise/A+规范
安装测试脚本
npm install -g promises-aplus-tests
然后在promise.js中加入
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
执行命令 promises-aplus-tests 文件名
promises-aplus-tests promise.js

以上代码通过完美全部测试用例
Promise.resolve()
// 参数为一般值,则直接返回,参数若为promise对象,则返回promise对象的结果
Promise.resolve = (value) => {
if (value instanceof Promise) {
return value
}
return new Promise((resolve, reject) => {
try {
if (value && value.then && typeof value.then === 'function') {
setTimeout(() => {
// value.then(
// value => {
// resolve(value)
// },
// reason => {
// reject(reason)
// }
// )
value.then(resolve,reject) // 上面代码的简写
})
} else {
resolve(value)
}
} catch(e) {
reject(e)
}
})
}
Promise.reject()
Promise.reject = (reason) => {
return new Promise((resolve, reject) => {
reject(reason)
})
}
Promise.all()
Promise.all = (promises) => {
return new Promise((resolve, reject) => {
if (promises && promises.length === 0) {
resolve([])
} else {
let values = [];
promises.forEach((fn, index) => {
Promise.resolve(fn).then(
value => {
values[index] = value
if (values.length === promises.length) {
resolve(values)
}
},
reason => {
reject(reason)
}
)
})
}
})
}
Promise.race()
Promise.race = (promises) => {
return new Promise((resolve, reject) => {
promises.forEach((fn, index) => {
Promise.resolve(fn).then(
value => {
resolve(value)
},
reason => {
reject(reason)
}
)
})
})
}
参考链接
Promise-B站
Promise/A+规范-翻译
Promise/A+规范 - 原文
对您有帮助的话,麻烦给个赞哦~