原生
<script>
const promise = new Promise((resolve, reject) => {
resolve();
// reject();
});
console.log(promise);
</script>
//Promise是一个构造函数
//参数为一个函数,且同步自调用了(这里称它为executor)
//executor中传入了两个函数,分别是resolve和reject,用来改变promise的状态
//promise的初始状态为pending
//promise的状态只能修改一次
MyPromise.prototype
实现resolve/reject
(function (w) {
function MyPromise(executor) {
// promise对象就是this,这是因为new关键字作用
const that = this;
/*
初始化promise对象是pending状态
_开头的属性是私有属性,外界不允许操作
*/
that._status = "pending";
// resolve函数将promise对象状态改成resolved
function resolve() {
// 让promise对象状态只能修改一次
if (that._status !== "pending") return;
// 如果不用that,这里的this指向是有问题的
that._status = "resolved";
}
// reject函数将promise对象状态改成rejected
function reject() {
if (that._status !== "pending") return;
that._status = "rejected";
}
// 同步调用
executor(resolve, reject);
}
w.MyPromise = MyPromise;
})(window);
- html
<body>
<script src="./01.promise.js"></script>
<script>
const promise = new MyPromise((resolve, reject) => {
resolve();
// reject()
});
console.log(promise);
</script>
</body>
实现then方法–基础
promise.then(
(value) => { },
(reason) => { }
)
1.then方法是promise实例对象使用的,所以定义在原型上
2.then方法是同步执行的
3.第一个参数是成功的回调,第二个参数是失败的回调
4.回调中可以接收到promise的结果值
- 当原型添加了then方法时,会将onResolve和onReject通过this传到promise实例对象身上
- 而在MyPromise构造函数中,通过that(这里替换了this,也是指向promsie实例对象)拿到这两个方法,在resolve和reject中调用
- onResolve和onReject都是异步函数
(function (w) {
function MyPromise(executor) {
const that = this;
that._status = "pending";
// 用来存储成功/失败回调函数的容器
that._callbacks = {};
function resolve(value) {
if (that._status !== "pending") return;
that._status = "resolved";
// 触发和调用onResolved函数,切记这里要异步去调用,因为代码同步执行的,这个时候原型上还没有添加这些方法
setTimeout(() => {
// that._callbacks.onResolved && that._callbacks.onResolved(value);
// 这个和上面的写法一样,但是是ES11的语法,2020年 新的运算符?.可选链
that._callbacks.onResolved?.(value);
}, 0);
}
function reject(error) {
if (that._status !== "pending") return;
that._status = "rejected";
// 如果不用定时器,这样子也可以
that._callbacks.onRejected && that._callbacks.onRejected(error);
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (onResolved, onRejected) {
/*
this指向实例对象promise
将成功/失败回调添加到容器中(注意没有调用,只是去添加这个属性,在调用回调的时候执行)
在Promise原型上添加then方法,方法中也是两个函数作为参数,分别是成功的回调和失败的回调
*/
this._callbacks.onResolved = onResolved;
this._callbacks.onRejected = onRejected;
};
w.MyPromise = MyPromise;
})(window);
<body>
<script src="./01.promise.js"></script>
<script>
const promise = new MyPromise((resolve, reject) => {
resolve(123);
// reject(777);
});
console.log(promise);
promise.then(
(value) => {
console.log("then方法成功回调---->" + value);
},
(error) => {
console.log("then方法失败回调---->" + error);
}
);
</script>
</body>
- 没有解决异步
then方法返回值/三种
- 调用then方法需要返回一个promise对象
- 因为promise的状态只能改变一次,所以我们需要返回一个新的promise对象
1.当then方法没有返回值,或者有返回值但不是promise对象时,默认返回一个新的成功的promise对象
2.当then方法返回一个promise对象需要判断是成功还是失败的peomsie对象
3.当then方法调用时,内部报错,需要返回一个失败的peomise对象
(function (w) {
function MyPromise(executor) {
const that = this;
that._status = "pending";
// 定义promise默认返回值
that._result = undefined;
that._callbacks = {};
function resolve(value) {
if (that._status !== "pending") return;
that._status = "resolved";
// 修改promise的返回值
that._result = value;
setTimeout(() => {
that._callbacks.onResolved?.(value);
});
}
function reject(error) {
if (that._status !== "pending") return;
that._status = "rejected";
// 修改promise的返回值
that._result = error;
setTimeout(() => {
that._callbacks.onRejected && that._callbacks.onRejected(error);
});
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (onResolved, onRejected) {
const that = this;
// 调用then方法,返回一个新的promise对象,这样才能实现then方法的链式调用
return new MyPromise((resolve, reject) => {
// then的返回值,取决于内部函数的返回值,怎么拿到这个函数内部返回值呢?小技巧
that._callbacks.onResolved = function (value) {
const resolvedRES = onResolved(value);
// 如果res的隐式原型在MyP的显示原型上,其实就是确认是peomise实例
if (resolvedRES instanceof MyPromise) {
resolvedRES.then(resolve, reject);
/*
实际这个是这样的简写
result.then(
(value) => resolve(value),
(reason) => reject(reason)
);
*/
} else {
// 说明没有返回值或者返回值不是promise
resolve(resolvedRES);
}
};
// 其实和resolve返回机制一样
this._callbacks.onRejected = function (error) {
const rejectedRES = onRejected(error);
if (rejectedRES instanceof MyPromise) {
rejectedRES.then(resolve, reject);
} else {
resolve(rejectedRES);
}
};
});
};
w.MyPromise = MyPromise;
})(window);
- html
<body>
<script src="./02.promise.js"></script>
<script>
const promise = new MyPromise((resolve, reject) => {
// resolve(123);
reject(777);
});
console.log(promise);
promise
.then(
(value) => {
console.log("then方法成功回调---->" + value);
},
(error) => {
return 50765
console.log("then方法失败回调---->" + error);
}
)
.then(
(value) => {
console.log("then2方法成功回调---->" + value);
},
(error) => {
console.log("then2方法失败回调---->" + error);
}
);
</script>
</body>
then方法返回值报错解决
- 就是在上面代码加了try catch而已
(function (w) {
function MyPromise(executor) {
const that = this;
that._status = "pending";
that._result = undefined;
that._callbacks = {};
function resolve(value) {
if (that._status !== "pending") return;
that._status = "resolved";
that._result = value;
setTimeout(() => {
that._callbacks.onResolved?.(value);
});
}
function reject(error) {
if (that._status !== "pending") return;
that._status = "rejected";
that._result = error;
setTimeout(() => {
that._callbacks.onRejected && that._callbacks.onRejected(error);
});
}
executor(resolve, reject);
}
MyPromise.prototype.then = function (onResolved, onRejected) {
const that = this;
return new MyPromise((resolve, reject) => {
that._callbacks.onResolved = function (value) {
// 加入了try tach
try {
const resolvedRES = onResolved(value);
if (resolvedRES instanceof MyPromise) {
resolvedRES.then(resolve, reject);
} else {
resolve(resolvedRES);
}
} catch (error) {
reject(error);
}
};
this._callbacks.onRejected = function (error) {
try {
const rejectedRES = onRejected(error);
if (rejectedRES instanceof MyPromise) {
rejectedRES.then(resolve, reject);
} else {
resolve(rejectedRES);
}
} catch (error) {
reject(error);
}
};
});
};
w.MyPromise = MyPromise;
})(window);
实现catch
- 借用then方法功能
// 在then方法函数中结局catch的报错
// // 为了then方法不传第二个函数(失败回调)服务
onRejected =
typeof onRejected === "function"
? onRejected
: (error) => {
throw error;
};
// 为了catch方法不传第一个回调服务
onResolved =
typeof onResolved === "function" ? onResolved : (value) => value;
// catch实际就是借用了then的方法
MyPromise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
- 不带try catch的报错
- 带try catch的报错
<body>
<script src="./02.promise.js"></script>
<script>
const promise = new MyPromise((resolve, reject) => {
resolve ();
// reject(777);
});
console.log(promise);
promise
.then((value) => {
console.log(11111, value);
})
// catch还是会执行,匹配的时候上一次是成功的,然后catch接收这个成功promise,是undefined,调用onResulved调用resolve报错
.catch((err) => {
console.log(22222, err);
})
.then((value) => {
console.log(33333, value);
})
.catch((reason) => {
console.log(4444, reason);
});
</script>
</body>
- 解决之后不会有报错
MyPromise方法:
resolve
// 给promise添加一个resolve方法
MyPromise.resolve = function (value) {
if (val instanceof MyPromise) {
return value;
}
return new MyPromise((resolve) => resolve(value));
};
reject
// 给promise添加一个reject方法
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason));
};
all
- 优化版
// all方法所有成功返回成功promise,有一个失败返回失败promise,失败的值就是第一个失败的值
MyPromise.all = function (promises) {
// 定义一个数组,用来保存成功的promise
const result = [];
// 传入数组的长度
const total = promises.length;
// 已经完成的数量
let completeNum = 0;
// 调用all方法会返回一个新的promise,all方法接收一个数组
return new MyPromise((resolve, reject) => {
// 去遍历这个传入的数组
promises.forEach((item, index) => {
if (item instanceof MyPromise) {
item.then(
(value) => {
// result[index] = value;
// completeNum++;
// if (total === completeNum) {
// resolve(result);
// }
Common(index, value);
},
// 这个方法是简写,完整版见下面
reject
);
} else {
// result[index] = item;
// completeNum++;
// if (total === completeNum) {
// resolve(result);
// }
Common(index, item);
}
});
// 不能定义在forEach 否则每次都会创建这个函数
function Common(index, value) {
result[index] = value;
completeNum++;
if (total === completeNum) {
resolve(result);
}
}
});
};
- 基础版
// all方法所有成功返回成功promise,有一个失败返回失败promise,失败的值就是第一个失败的值
MyPromise.all = function (promises) {
// 定义一个数组,用来保存成功的promise
const result = [];
// 传入数组的长度
const total = promises.length;
// 已经完成的数量
let completeNum = 0;
// 调用all方法会返回一个新的promise,all方法接收一个数组
return new MyPromise((resolve, reject) => {
// 去遍历这个传入的数组
promises.forEach((item, index) => {
if (item instanceof MyPromise) {
item.then(
(value) => {
result[index] = value;
completeNum++;
if (total === completeNum) {
resolve(result);
}
},
(reason) => reject(reason)
);
} else {
result[index] = item;
completeNum++;
if (total === completeNum) {
resolve(result);
}
}
});
});
};
// 注意这里要写自定义的promise,否则不会进入判断,直接renturn这个promise到数组
const p = new MyPromise((resolve) => resolve(777));
// const f = new MyPromise((resolve, reject) => reject(9999));
const res = MyPromise.all([111, 222, 333,p]);
console.log(res)
allSetteld
/*
只要里边的promise对象没有执行完成,则allSettled返回pending状态的promise对象
只要里边的promise对象全部完成了,则allSettled返回fulfilled状态的promise对象(无论是否所有的promise都失败了)
当所有的请求完成,allSettled的状态值就是成功,allSettled的value就是一个数组,包含了所有的方法内返回promise对象
*/
MyPromise.allSetteld = function (promises) {
// 调用allSetteld方法,返回一个promise
return new MyPromise((resolve) => {
// 声明一个数组,保存成功的值
const result = [];
// 得到传入数组的数量
const total = promises.length;
// 已经完成的数量
let completeNum = 0;
promises.forEach((item, index) => {
if (item instanceof MyPromise) {
item.then(
(value) => {
result[index] = {
status: "resolved",
value,
};
completeNum++;
if (total === completeNum) {
resolve(result);
}
},
(reason) => {
result[index] = {
state: "rejected",
reason,
};
completeNum++;
if (total === completeNum) {
resolve(result);
}
}
);
} else {
result[index] = {
state: "resolved",
value: item,
};
completeNum++;
if (total === completeNum) {
resolve(result);
}
}
});
});
};
const p = new MyPromise((resolve) => {
setTimeout(() => {
resolve(777);
}, 2000);
});
const f = new MyPromise((resolve, reject) => reject(9999));
const res = MyPromise.allSetteld([111, 222, 333, p, f]);
console.log(res);
setTimeout(()=>{
console.log(res)
},3000)