Promise的作用
Promise 翻译过来就是承诺的意思,这个承诺会在未来有一个确切的答复,并且该承诺有三种状态,分别是: 等待中(pending);完成了 (resolved);拒绝了(rejected)
这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 resolved 后,就不能再次改变
当我们在构造 Promise 的时候,构造函数内部的代码是立即执行的
如:
new Promise((resolve, reject) => {
console.log('new Promise')
resolve('success')
})
console.log('finifsh')
这里的“new Promise”会在“finifsh”之前执行。
Promise 实现了链式调用,也就是说每次调用 then 之后返回的都是一个 Promise,并且是一个全新的 Promise,原因也是因为状态不可变。如果你在 then 中 使用了 return,那么 return 的值会被 Promise.resolve() 包装。Promise 也很好地解决了回调地狱的问题。
它也是存在一些缺点的,比如无法取消 Promise,错误需要通过回调函数捕获
手写Promise
内容较多,谨慎观看
<script>
//定义三个常量,表示状态
const PENDING = 'pending';//等待
const RESOLVED = 'resolved';//成功
const REJECTED = 'rejected';//失败
function MyPromise(fn) {
const that = this;//创建常量,因为代码可能会异步执行,用于获取正确的this的对象;
that.state = PENDING;//promise的初始状态为pending
that.value = null;//value变量用于保存resolve或者reject中传入的值
that.resolvedCallbacks = [];//用于保存then中的回调
that.rejectedCallbacks = [];//用于保存then中的回调
//下一步完善resolve和reject函数
//resolve和reject函数,
// 首先都要判断当前状态是否为pending,因为根据promise的规范规定只有pending状态才可以改变状态
//其次改变当前的状态,是resolved或者rejected,并将传入的值赋值个value
//最后遍历回调函数并执行
function resolve(value) {
// if(that.state === PENDING){
// that.state = RESOLVED;
// that.value = value;
// that.resolvedCallbacks.map(cb => cb(that.value));
// }
//为符合promise/A+规范,对代码进行改造
//首先判断传入的值是否为promise类型
//其次为保证函数的执行顺序,需要将两个函数体代码使用setTimeout包裹起来
if(value instanceof MyPromise){
return value.then(resolve,reject)
}
setTimeout( () => {
if(that.state === PENDING){
that.state = RESOLVED;
that.value = value;
that.resolvedCallbacks.map(cb => cb(that.value));
}
},0)
}
function reject(value) {
// if(that.state === PENDING){
// that.state = REJECTED;
// that.value = value;
// that.rejectedCallbacks.map(cb => cb(that.value));
// }
//为符合promise/A+规范,对代码进行改造
setTimeout( () => {
if(that.state === PENDING){
that.state = REJECTED;
that.value = value;
that.rejectedCallbacks.map(cb => cb(that.value));
}
},0)
}
//下一步完善执行fn函数
//首先执行传入的参数并将之前的resolve和reject当做参数传进去
//其次在执行函数的过程中可能会遇到错误,需要捕获错误并执行reject函数
try{
fn(resolve,reject)
}catch (e) {
reject(e)
}
}
//实现then函数
//首先判断两个参数是否为函数类型,因为两个参数是可选参数
//当参数不是函数类型时,需要创建一个函数赋值个对应的参数,同时也实现了透传
//最后判断状态,当状态不是pending时,就去执行对应的函数。如果状态是pending时,就往回调函数中push进函数
MyPromise.prototype.then = function (onFulfilled,onRejected) {
// const that = this;
// onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
// onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r};
// if(that.state === PENDING){
// that.resolvedCallbacks.push(onFulfilled);
// that.rejectedCallbacks.push(onRejected);
// }
// if(that.state === RESOLVED){
// onFulfilled(that.value);
// }
// if(that.state === REJECTED){
// onRejected(that.value);
// }
//为符合promise/A+规范,对代码进行改造
let newPromise;//新增一个变量,每一个then函数都会返回一个新的promise对象,该变量用于保存新的返回对象
const that = this;
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason;};
if(that.state === PENDING){
return (newPromise = new MyPromise((resolve,reject) => {//返回一个新的promise对象,并传入一个函数
that.resolvedCallbacks.push( () => {//往回调函数push新的函数
try{//执行过程中,可能遇到错误,使用try...catch包裹
const x = onFulfilled(that.value);//执行函数时,返回一个x
resolutionProcedure(newPromise,x,resolve,reject);//执行promise解决过程
}catch (reason) {
reject(reason)
}
});
that.rejectedCallbacks.push( () => {
try{
const x = onRejected(that.value);
resolutionProcedure(newPromise,x,resolve,reject);
}catch (reason) {
reject(reason)
}
})
}))
}
if(that.state === RESOLVED){
return (newPromise = new MyPromise((resolve,reject) => {
setTimeout( () => {
try {
const x = onFulfilled(that.value);
resolutionProcedure(newPromise,x,resolve,reject);
}catch (reason) {
reject(reason)
}
})
}))
}
if(that.state === REJECTED){
return (newPromise = new MyPromise((resolve,reject) => {
setTimeout( () => {
try {
const x = onRejected(that.value);
resolutionProcedure(newPromise,x,resolve,reject);
}catch (reason) {
reject(reason)
}
})
}))
}
};
function resolutionProcedure(newPromise,x,resolve,reject) {
if (newPromise === x){//规定newPromise不能与x相等
return reject(new TypeError('Error'));
}
if(x instanceof MyPromise){//如果x为promise时;第一,当x处于等待状态,promise需保持等待状态直到x被执行或拒绝
x.then((value) => {//第二,当x处于其他状态时,则用相同的值处理promise
resolutionProcedure(newPromise,value,resolve,reject);
},reject)
}
let called = false;//创建一个变量,用于判断是否已经调用过函数
if(x !== null && (typeof x === 'object' || typeof x === 'function')){//判断x是否为对象或者是函数
try{//如果x是对象或者函数
let then = x.then;//将x.then赋值给then
if(typeof then === 'function'){//判断then的类型是否为函数
then.call(//如果then为函数类型,
x,//就将 x 作为函数的作用域 this 调用之,并且传递两个回调函数作为参数
y => {//第一个参数叫做 resolvePromise,需要判断是否已经执行过函数,然后进行相应的逻辑
if(called) return;
called = true;
resolutionProcedure(newPromise,y,resolve,reject);
},
e => {//第二个参数叫做 rejectPromise,需要判断是否已经执行过函数,然后进行相应的逻辑
if(called) return;
called = true;
reject(e);
}
)
}else {
resolve(x);//如果then不是函数类型,将x传入resolve中
}
}catch (e) {//将错误抛出
if (called) return ;
called = true;
reject(e);
}
}else {
resolve(x);//如果x不是对象或者函数,将x传入resolve中
}
}
new MyPromise((resolve,reject) => {
setTimeout( () => {
resolve(1)
},0)
}).then(value => {
console.log(value);//1
})
</script>