promise专题--手写promise03

上篇回顾

promise专题–手写promise02
上篇我们解决了异步调用的问题,但是发现链式调用是行不通的。这篇解决这个问题。

一、问题分析

原生promise为什么支持then的链式调用?因为原生每次then之后会返回一个promise对象,所以可以支持链式调用,但是上篇我们写的并没有返回一个promise对象,所以当我们再then的时候,就是undefined.then,所以理所当然直接报错喽,所以链式调用的核心就是要返回一个promise对象,下面看怎么做!

二、重写then方法

1、因为要返回一个promise对象,所以我们直接搭建新的代码框架,具体为

	Promise.prototype.then = function (onFulfilled, onRejected) {
		let newPromise = new Promise((resolve, reject) => {})
		return newPromise ;
	}

2、重写上一篇的三种情况,因为每次返回一个promise,所以我们得知道上一个执行的到底是成功了还是失败了,所以当拿到结果的时候我们需要一个方法来解析这个promise到底是成功了还是失败了。

	Promise.prototype.then = function (onFulfilled, onRejected) {
		let newPromise = new Promise((resolve, reject) => {
			if (_this.status === "fulfilled") {
          	   setTimeout(() => {
                // 需要使用newPromise,所以需要放入异步代码中
                try {
                    let res = onFulfilled(_this.successValue);
                    //resolve(res);
                    // 对res进行解析判断
                    resolvePromise(promise2, res, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            }, 0)
        }
	})
		return newPromise ;
	}
	function resolvePromise(promise,res, resolve, reject) {
		// 这里需要判断一个循环引用的问题
		if (res === promise) {
	        return reject(new TypeError("循环引用!"));
	    }
	    // 判断是否是一个对象或者函数
	    if (res != null && typeof res === 'object' || typeof res === 'function') {
	        // 判断是否是promise
	        try {
	            let then = res.then; // then有可能抛出异常
	            if (typeof then === 'function') {
	                // 将其认为是一个promise,然后执行then
	                then.call(res, (y) => {
	                    resolve(y);
	                }, (r) => {
	                    reject(r);
	                });
	            } else {
	                // 认为是一个普通的值
	                resolve(res);
	            }
	        }catch (e) {
	            reject(e);
	        }
	
	    } else {
	        // 非引用类型 也就是一个普通值
	        resolve(res);
	    }
}

3、失败和异步的重写如下,整体代码如下:

	Promise.prototype.then = function (onFulfilled, onRejected) {
	    let _this = this;
	    // then被执行,需要再次返回一个新的promise实例
	    // 需要拿到当前then方法的结果也就是得知道成功或者失败
	    let newPromise = new Promise((resolve, reject) => {
	        if (_this.status === "fulfilled") {
	            setTimeout(() => {
	                // 需要使用promise2,所以需要放入异步代码中
	                try {
	                    let res = onFulfilled(_this.successValue);
	                    //resolve(res);
	                    // 对res进行解析判断
	                    resolvePromise(newPromise, res, resolve, reject);
	                } catch (e) {
	                    reject(e);
	                }
	            }, 0)
	        }
	
	        if (_this.status === "rejected") {
	            setTimeout(() => {
	                try {
	                    let res = onRejected(_this.errReason);
	                    resolvePromise(newPromise, res, resolve, reject);
	                } catch (e) {
	                    reject(e);
	                }
	            }, 0)
	        }
	
	        if (_this.status === "pending") {
	            _this.onResolvedCallbacks.push(function () {
	                setTimeout(() => {
	                    try {
	                        let res = onFulfilled(_this.successValue);
	                        resolvePromise(newPromise, res, resolve, reject);
	                    } catch (e) {
	                        reject(e);
	                    }
	                }, 0)
	            })
	            _this.onRejectedCallbacks.push(function () {
	                setTimeout(() => {
	                    try {
	                        let res = onRejected(_this.errReason);
	                        resolvePromise(newPromise, res, resolve, reject);
	                    } catch (e) {
	                        reject(e);
	                    }
	                }, 0)
	
	            })
	        }
	    });
	    return newPromise;
}

三、大体思路

1.能够链式调用,肯定then方法最后需要返回一个Promise实例;
2. 在then方法中用res去接收成功或者失败的返回值,当成功或失败方法抛出错误,直接执行reject。因为要分析成功或者失败的回调,所以专门抽出一个方法resolvePromise用来分析返回值;
3. resolvePromise方法中传入了四个参数,then中的newPromise,res值;
4. 如果res与promise相等,说明重复引用了,直接报错干掉;
5. 当res不是null,是个对象类型or函数类型,并且他的then方法也是函数类型时,就可以认为res他是个promise实例,执行x.then()方法;再用resolvePromise方法分析他的成功的返回值即可;
6. 如果res不是null不是object或function,就可以将其认为一个普通值,执行resolve方法即可;
7. 如果res.then方法抛出异常了,直接调用reject方法就ok喽;

四、支持then穿透

原生promise支持then穿透也就是

	p.then().then().then(()= > {....})

如何实现?
思路: then方法返回执行promise前,判断下,如果是穿透的话,返回的不是一个function类型,处理下就ok

	Promise.prototype.then = function (onFulfilled, onRejected) {
	    // 穿透处理
	    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data;
	    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
	        throw reason
	    }
	    .......
   }

下一篇实现all, race, resolve,reject,catch,finally方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是手写Promise实现: ```javascript class MyPromise { constructor(executor) { this.status = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.status === 'pending') { this.status = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(fn => fn()); } }; const reject = (reason) => { if (this.status === 'pending') { this.status = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }; const promise2 = new MyPromise((resolve, reject) => { if (this.status === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } if (this.status === 'rejected') { setTimeout(() => { try { const x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } if (this.status === 'pending') { this.onResolvedCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } } function resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { return reject(new TypeError('Circular reference')); } if (x instanceof MyPromise) { x.then(value => { resolvePromise(promise2, value, resolve, reject); }, reject); } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) { let then; try { then = x.then; if (typeof then === 'function') { then.call(x, value => { resolvePromise(promise2, value, resolve, reject); }, reason => { reject(reason); }); } else { resolve(x); } } catch (error) { reject(error); } } else { resolve(x); } } ``` 以上是一个基本的Promise实现,它具有Promise的基本特性,包括状态管理、异步操作、链式调用、错误处理等。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [超详细!一次性搞懂手写Promise全过程](https://blog.csdn.net/qq_41852789/article/details/128453341)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Promise学习-手写一个promise](https://blog.csdn.net/qq_42161935/article/details/120672260)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值