本文主要是介绍手写Promise then/catch/resolve/reject all/allSetteld,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原生
<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对象状态改成resolvedfunction resolve() {// 让promise对象状态只能修改一次if (that._status !== "pending") return;// 如果不用that,这里的this指向是有问题的that._status = "resolved";}// reject函数将promise对象状态改成rejectedfunction 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 {// 说明没有返回值或者返回值不是promiseresolve(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 50765console.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 tachtry {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) {// 定义一个数组,用来保存成功的promiseconst 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) {// 定义一个数组,用来保存成功的promiseconst 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方法,返回一个promisereturn 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)
这篇关于手写Promise then/catch/resolve/reject all/allSetteld的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!