Promise 对象概要
基础用法
工作原理
Promise.prototype.then()
Promise.prototype.catch()
Promise.prototype.finally()
Promise.resolve()
Promise.reject()
Promise.all()
Promise.race()
Promise.allSettled()
Promise.any()
Promise 扩展
构造函数封装 Promise 对象
class 类封装 Promise 对象
一、Promise 对象介绍
Promise 是一个异步解决方案,其本质是一个构造函数,调用时需要使用 new 命令符。该构造函数接收一个函数作为参数,返回一个 Promise 实例对象。该函数参数有两个参数,且这两个参数都是函数,第一个函数参数(resolve)在异步成功时调用,一旦调用过后,Promise 的状态就会变成已完成(成功)。第二个函数参数(reject)在异步失败时调用,调用过后,Promise 的状态就会变成已失败,而且 Promise 的状态只会改变一次,一旦状态改变后,就不会再次发生变化,且任何时候调用 Promise 都是能得到这个结果。
Promise 对象有三个状态,分别是初始化时的未完成 pending,已成功 resolved 或 fulfilled,,已失败 rejected。
Promise 对象状态的改变有两种情况,一种是由未完成变成已完成,即从 pending 到 resolved 或 fulfilled,另一种情况是由未完成到已失败,即从 pending 到 rejected。
1、Promise 的基本用法。
const p = new Promise((resolve, reject) => { // 返回一个 promise 实例对象
if(true) {
resolve();
} else {
reject();
}
})
console.log(p);
2、Promise 的工作流程。Promise 的参数函数,称之为 执行器 函数,当对 Promise 使用 new 命令符时,执行器函数会立即执行,且执行器函数内部的代码为同步代码。如果 Promise 存在异步操作,当操作成功时,调用执行器函数的第一个参数函数 resolve(),使得 Promise 的状态会变为已完成;当操作结果失败时,则调用 Promise 的第二个参数函数 reject(),使得 Promise 状态变为已失败。
const p = new Promise((resolve, reject) => {
console.log('hello');
if(true) {
resolve();
} else {
reject();
}
})
console.log('world');
// 输出结果,先输出 'hello',在输出 'world'
上面代码的输出结果是,先输出 'hello', 再输出 'world',证明执行器函数内部的代码是同步代码。
Promise执行器函数内部执行 resolve()或reject()回调的时候传递的参数,就是返回的promise实例对象的结果值。
const p = new Promise((resolve, reject) => {
if(true) {
resolve('成功');
} else {
reject('失败');
}
})
// new Promise中执行了resove('成功')回调
// 因此返回的实例对象p的状态属于成功,resolve('成功')传递的值就是p的值
// 在控制台可以看到 p的属性[[promiseResult]]: '成功'
console.log(p)
3、Promise.prototype.then() 方法,Promise 执行的返回结果是一个 Promise 实例对象,该实例对象有个 then() 方法,接收两个参数函数。当 Promise 的状态会变为已完成(成功)时,调用 then() 方法的第一个回调函数。当 Promise 的状态变为失败或抛出错误时,则调用 then() 方法的第二个参数函数。then()方法返回一个新的promise实例对象,它的状态由then()方法的执行的回调返回值决定:
(1)当then方法的回调的返回值是一个非promise对象时,then()方法返回的是一个成功的promise实例对象。
(2)当then方法的回调的返回值是一个promise对象时,该对象的状态决定了最终then()方法返回的promise对象的状态,而且该对象的值就是then()方法返回的promise对象的值。
const p = new Promise((resolve, reject) => {
resolve('成功');
})
//(1)
const res = p.then(value => {
return 123
}, reason => {
console.log(reason);
})
res.then(value => console.log(value)) // 输出123
// p是一个成功的promise对象,因此执行then()方法的第一个回调
// 该回调返回数字123(非promise对象)
// 因此最终的返回的promise对象res是一个成功的promise对象,值为123
//(2)then回调是个成功的promise
const res = p.then(value => {
return new Promise((resolve, reject) => {
resolve('success');
})
}, reason => {
console.log(reason);
})
res.then(value => console.log(value)) // 输出success
// p是一个成功的promise对象,因此执行then()方法的第一个回调
// 该回调返回一个新的成功的promise对象,值为success
// 因此最终的返回的promise对象res是一个成功的promise对象,值为success
//(2)then回调是个失败的promise
const res = p.then(value => {
return new Promise((resolve, reject) => {
reject('fail');
})
}, reason => {
console.log(reason);
})
res.then(() => (), reason => console.log(reason)) // 输出fail
// p是一个成功的promise对象,因此执行then()方法的第一个回调
// 该回调返回一个新的失败的promise对象,值为fail
// 因此最终的返回的promise对象res是一个失败的promise对象,值为fail
then()方法返回的结果依旧是一个promise实例对象,因此,可以链式调用then()方法。
const p = new Promise((resolve, reject) => {
if(true) {
resolve('成功');
} else {
reject('失败');
}
})
p.then(value => {
console.log(value);
}, reason => {
console.log(reason);
}).then()
当Promise的执行器函数抛出错误时,then()方法会执行第二个回调。
const p = new Promise((resolve, reject) => {
throw '失败了'
})
p.then(value => alert(value), reason => console.log(reason))
// 执行then()方法的第二个回调,输出 ‘失败了’
4、Promise.prototype.catch() 方法,专门用来指定 Promise 实例对象发生错误时的回调,因此,then() 方法里面可以不写失败回调,而是把失败回调最后放到 catch() 方法里面。catch() 方法是 then(null, rejection) 或 then(undefined, rejection) 的别名, 本质依旧是一个 then() 方法。
const p = new Promise((resolve, reject) => {
if(true) {
resolve();
} else {
reject();
}
})
p.then(vlaues => {
console.log('成功');
}).catch(reason => {
console.log('失败');
})
5、Promise.prototype.finally() 方法,用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
const p = new Promise((resolve, reject) => {
if(true) {
resolve();
} else {
reject();
}
})
p.then(vlaues => {
console.log('成功');
}).catch(reason => {
console.log('失败');
}).finally(() => {
console.log('这是最后执行的回调');
})
6、Promise.resolve() 方法,接收一个值作为参数,用于将参数值快速转化成一个 Promise 对象实例。该方法返回的 Promise 对象的结果由参数决定。
如果参数是一个非 Promise 对象,无论是 null、undefined、还是其他类型数据,返回的都是一个状态为成功的 Promise 实例对象。
/ p 是一个状态成功的 Promise 实例对象
const p = Promise.resolve(9527)
p.then(value => console.log(value))
// 输出结果 9527
如果参数是一个 Promise 对象,则返回的 Promise 实例对象的状态由该参数的状态决定。
const p = Promise.resolve(new Promise((resolve, reject) => {
if(true) {
resolve();
} else {
reject();
}
}))
// 实例对象 p 的状态参数 new Promise(...) 的状态决定
// 当参数对象的状态为成功,p 的状态就成功,而且参数对象返回的成功的值就是 p 的值
// 当参数对象的状态为失败,p 的状态就失败,而且参数对象返回的失败的值就是 p 的值
7、Promise.reject() 方法,快速返回一个 Promise 对象实例,该实例的状态为 rejected。
const p = Promise.reject('出错了')
p.catch(reason => console.log(reason))
8、Promise.all() 方法,用于将多个 Promise 实例对象,包装成一个新的 Promise 实例,该方法接收一个 Promise 对象组成的数组作为参数。当所有数组成员的 Promise 状态都为成功时,Promise.all() 返回的实例的状态就为成功。当数组成员中有一个 Promise 对象的状态为失败,则整个 Promise.all() 返回的实例的状态就为失败。且 Promise.all() 方法的返回结果就是各个 Promise 对象的成功返回值组成的一个数组。
const p1 = new Promise((resolve, reject) => {
resolve('成功')
})
const p2 = Promise.resolve('success')
const pro = Promise.all([p1, p2])
pro.then(values => console.log(values))
// pro 的状态为成功,输出结果为 ['成功', 'success']
9、Promise.race() 方法,用于将多个 Promise 实例对象,包装成一个新的 Promise 实例,该方法接收一个 Promise 对象组成的数组作为参数。返回的实例对象的状态由数组成员中最先改变状态的 Promise 对象决定。该最先改变状态的 Promise 的状态为成功时,Promise.race() 返回的实例的状态就为成功。该最先改变状态的 Promise 的状态为失败,则整个 Promise.race() 返回的实例的状态就为失败。且 Promise.race() 方法结果就是最先改变状态的 Promise 对象的返回结果。
const p1 = new Promise((resolve, reject) => {
resolve('成功')
})
const p2 = Promise.resolve('success')
const pro = Promise.race([p1, p2])
pro.then(values => console.log(values))
// pro 的状态为成功,输出结果为 ['成功']
10、Promise.allSettled() 方法,用于确保一组异步操作都完成后(不论成功或失败,全都返回结果),在执行下一步操作。该方法接收一个 Promise 对象组成的数组作为参数。返回的新的 Promise 实例,一旦发生状态变更,状态总是 fulfilled ,不会变成 rejected。
const p1 = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('成功');
console.log(8888);
}, 1000)
})
const p2 = Promise.resolve('success')
await Promise.allSettled([p1, p2])
console.log(9999);
// 结果,等待1秒后,先输出 8888,再输出 9999
11、Promise.any() 方法,用于将多个 Promise 实例对象,包装成一个新的 Promise 实例,该方法接收一个 Promise 对象组成的数组作为参数。数组成员的 Promise 只要有一个状态变为成功时,Promise.any() 返回的实例的状态就为成功,Promise.any() 方法的值就是第一个成功的 Promise 对象返回的值。当数组成员中所有的 Promise 对象的状态都为失败时,则整个 Promise.any() 返回的实例的状态就为失败。
const p1 = new Promise((resolve, reject) => {
reject('失败')
})
const p2 = Promise.resolve('success')
const pro = Promise.any([p1, p2])
pro.then(values => console.log(values)).catch(err => console.log(err))
// 输出结果,'success'
二、Promise 扩展
1、Promise 对象有三种状态,初始化时的未完成状态 pending,成功时的状态 resolved (fulfilled) 及失败时的状态 rejected。Promise 对象状态的变化只要两种情况,pending => fulfilled 或 pending => rejected。而改变 Promise 对象状态的方式共有三种。
(1)、调用 resolve(),一旦在 Promise 对象内部调用了该方法,其状态就会变成已完成(成功)。
(2)、调用 reject(),该方法调用后,Promise 对象的状态就会变成已失败。
(3)、直接抛出错误 throw new Error('失败')
const p = new Promise((resolve, reject) => {
throw new Error('失败了')
})
p.catch(err => console.log(err))
2、为 Promise 对象指定都多个回调,在 Promise 状态发生改变时,所有指定的回调都会执行。
const p = Promise.resolve('成功')
p.then(value => console.log('111'))
p.then(value => console.log('222'))
// 输出结果,先输出 111,再输出 222,两个 then() 方法的回调都执行
三、Promise 封装
1、使用构造函数封装。
export default function Promise(excutor) {
this.promiseState = 'pending';
this.promiseResult = null;
this.callbacks = [];
// 执行器函数成功回调
const resolve = (data) => {
// 调用过后,改变 promise 状态为成功
if(this.promiseState !== 'pending') return;
this.promiseState = 'fulfilled';
this.promiseResult = data;
// 执行异步任务的回调
this.callbacks.length && setTimeout(() => {
this.callbacks.forEach(item => {
item.onResolved(data);
});
});
};
// 执行器函数失败回调
const reject = (data) => {
// 调用过后,改变 promise 状态为失败
if(this.promiseState !== 'pending') return;
this.promiseState = 'rejected';
this.promiseResult = data;
// 执行异步任务的回调
this.callbacks.length && setTimeout(() => {
this.callbacks.forEach(item => {
item.onRejected(data);
});
});
};
try {
excutor(resolve, reject);
} catch(e) {
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
(typeof onResolved !== 'function') && (onResolved = values => values);
(typeof onRejected !== 'function') && (onRejected = reason => {
throw reason;
});
return new Promise((resolve, reject) => {
const callback = onCallbackType => {
try {
// 获取promise成功时then方法的第一个回调的结果值
const result = onCallbackType(this.promiseResult);
if(result instanceof Promise) {
// 结果是一个promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
});
} else {
// 结果是一个非promise对象
resolve(result);
}
} catch(e) {
reject(e);
}
}
// Promise 状态变为成功时,执行 then 方法的第一个回调
if(this.promiseState === 'fulfilled') {
setTimeout(() => {
callback(onResolved);
});
}
// Promise 状态变为失败时,执行 then 方法的第二个回调
if(this.promiseState === 'rejected') {
setTimeout(() => {
callback(onRejected);
});
}
// 当promise存在异步任务,把then回调储存起来
if(this.promiseState === 'pending') {
this.callbacks.push({
onResolved: () => {
callback(onResolved);
},
onRejected: () => {
callback(onRejected);
}
});
}
});
}
// 添加catch方法
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
}
// 添加finally方法
Promise.prototype.finally = function(callback) {
return this.then(v => {
callback();
return Promise.resolve(v);
}, r => {
callback();
throw r;
})
}
// 添加resolve方法
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
if(value instanceof Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
});
} else {
resolve(value);
}
});
}
// 添加reject方法
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
// 添加all方法
Promise.all = function(promiseArr) {
let count = 0;
let arr = [];
return new Promise((resolve, reject) => {
promiseArr.forEach((item, index) => {
item.then(v => {
count++;
arr[index] = v;
(count === promiseArr.length) && resolve(arr);
}, r => {
reject(r);
});
});
});
}
// 添加race方法
Promise.race = function(promiseArr) {
return new Promise((resolve, reject) => {
promiseArr.forEach(item => {
item.then(v => {
resolve(v);
}, r => {
reject(r);
});
});
});
}
// 添加any方法
Promise.any = function(promiseArr) {
let count = 0;
return new Promise((resolve, reject) => {
promiseArr.forEach(item => {
item.then(v => {
resolve(v);
}, r => {
count++;
(count === promiseArr.length) && reject('All promises were rejected');
});
});
});
}
// 添加allSettled方法
Promise.allSettled = function(promiseArr) {
let count = 0;
let arr = [];
return new Promise((resolve, reject) => {
promiseArr.forEach((item, index) => {
item.then(v => {
arr[index] = {
status: 'fulfilled',
value: v
};
count++;
(count === promiseArr.length) && resolve(arr);
}, r => {
arr[index] = {
status: 'rejected',
reason: r
};
count++;
(count === promiseArr.length) && resolve(arr);
});
});
});
}
使用 class 类封装。
export default class Promise {
constructor(excutor) {
this.promiseState = 'pending';
this.promiseResult = null;
this.callbacks = [];
// 执行器函数成功回调
const resolve = (data) => {
// 调用过后,改变 promise 状态为成功
if(this.promiseState !== 'pending') return;
this.promiseState = 'fulfilled';
this.promiseResult = data;
// 执行异步任务的回调
this.callbacks.length && setTimeout(() => {
this.callbacks.forEach(item => {
item.onResolved(data);
});
});
};
// 执行器函数失败回调
const reject = (data) => {
// 调用过后,改变 promise 状态为失败
if(this.promiseState !== 'pending') return;
this.promiseState = 'rejected';
this.promiseResult = data;
// 执行异步任务的回调
this.callbacks.length && setTimeout(() => {
this.callbacks.forEach(item => {
item.onRejected(data);
});
});
};
try {
excutor(resolve, reject);
} catch(e) {
reject(e);
}
}
// 添加then方法
then(onResolved, onRejected) {
(typeof onResolved !== 'function') && (onResolved = values => values);
(typeof onRejected !== 'function') && (onRejected = reason => {
throw reason;
});
return new Promise((resolve, reject) => {
const callback = onCallbackType => {
try {
// 获取promise成功时then方法的第一个回调的结果值
const result = onCallbackType(this.promiseResult);
if(result instanceof Promise) {
// 结果是一个promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
});
} else {
// 结果是一个非promise对象
resolve(result);
}
} catch(e) {
reject(e);
}
}
// Promise 状态变为成功时,执行 then 方法的第一个回调
if(this.promiseState === 'fulfilled') {
setTimeout(() => {
callback(onResolved);
});
}
// Promise 状态变为失败时,执行 then 方法的第二个回调
if(this.promiseState === 'rejected') {
setTimeout(() => {
callback(onRejected);
});
}
// 当promise存在异步任务,把then回调储存起来
if(this.promiseState === 'pending') {
this.callbacks.push({
onResolved: () => {
callback(onResolved);
},
onRejected: () => {
callback(onRejected);
}
});
}
});
}
// 添加catch方法
catch(onRejected) {
return this.then(undefined, onRejected);
}
// 添加finally方法
finally(callback) {
return this.then(v => {
callback();
return Promise.resolve(v);
}, r => {
callback();
throw r;
})
}
// 添加resolve方法
static resolve(value) {
return new Promise((resolve, reject) => {
if(value instanceof Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
});
} else {
resolve(value);
}
});
}
// 添加reject方法
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
// 添加all方法
static all(promiseArr) {
let count = 0;
let arr = [];
return new Promise((resolve, reject) => {
promiseArr.forEach((item, index) => {
item.then(v => {
count++;
arr[index] = v;
(count === promiseArr.length) && resolve(arr);
}, r => {
reject(r);
});
});
});
}
// 添加race方法
static race(promiseArr) {
return new Promise((resolve, reject) => {
promiseArr.forEach(item => {
item.then(v => {
resolve(v);
}, r => {
reject(r);
});
});
});
}
// 添加any方法
static any(promiseArr) {
let count = 0;
return new Promise((resolve, reject) => {
promiseArr.forEach(item => {
item.then(v => {
resolve(v);
}, r => {
count++;
(count === promiseArr.length) && reject('All promises were rejected');
});
});
});
}
// 添加allSettled方法
static allSettled(promiseArr) {
let count = 0;
let arr = [];
return new Promise((resolve, reject) => {
promiseArr.forEach((item, index) => {
item.then(v => {
arr[index] = {
status: 'fulfilled',
value: v
};
count++;
(count === promiseArr.length) && resolve(arr);
}, r => {
arr[index] = {
status: 'rejected',
reason: r
};
count++;
(count === promiseArr.length) && resolve(arr);
});
});
});
}
}