promise专题--手写promise02

上篇回顾

promise专题–手写promise01
上篇我们初步完成了基本的promise,但是发现当使用异步调用的时候是行不通的。这篇解决这个问题。

一、优化promise类和then方法

上一篇说道,当resolve或者reject被异步函数包裹的时候,他们没有执行,也就是如下这种情况

	/*原因如下:
	因为setTimeout是异步函数,所以resolve是最后执行的,先执行同步操作,
	也就是说先打印出ok,然后调用then方法,
	此时status还是pending的状态,所以不会执行onFulfilled
	也就不会打印7777
	之后再调用resolve*/
	new Promise((resolve, reject) => {
	    setTimeout(() => {
	        resolve("7777"); // 此时不会执行
	        // reject("卧槽,失败了");
	    })
		console.log("ok"); // 第一步执行
		
	});
function Promise(executor) {
    let _this = this;
    _this.status = "pending"; // 默认状态是等待态
    _this.successValue = undefined;
    _this.errReason = undefined;

    function resolve(value) {
        // 只能从等待态变成成功
        // 等到执行异步,也就是第三步会执行这里
        if (_this.status === "pending") {
            _this.status = "fulfilled"; // 状态变成成功
            _this.successValue = value;
        }
    }

    function reject(reason) {
        if (_this.status === "pending") {
            _this.status = "rejected"; // 状态变成失败
            _this.errReason = reason;
        }
    }
    executor(resolve, reject);
}	
Promise.prototype.then = function (onFulfilled, onRejected) {
    let _this = this;
	console.log(_this.status)// 此时状态是pending,第二步执行
    if (_this.status === "fulfilled") {
        onFulfilled(_this.value)
    }

    if (_this.status === "rejected") {
        onRejected(_this.reason)
    }
}

解决方法分析:
当then中status为pending的时候说明有异步,此时并没有明确到底该执行resolve还是reject,此时我们将两者的回调全部放入一个各自的数组中存储起来,然后当最后执行resolve或者reject的时候,将数组中存储的函数执行一遍即可.


二、优化后支持异步代码

	function Promise(executor) {

    let _this = this;
    _this.status = "pending"; // 默认状态是等待态
    _this.successValue = undefined;
    _this.errReason = undefined;
    _this.onResolvedCallbacks = [] // 成功时调用的数组
    _this.onRejectedCallbacks = [] // 失败时调用的数组
    function resolve(value) {
        // 只能从等待态变成成功
        if (_this.status === "pending") {
            _this.status = "fulfilled"; // 状态变成成功
            _this.successValue = value;
            // 循环数组执行函数
            _this.onResolvedCallbacks.forEach(fn=>fn())
        }
    }
    function reject(reason) {
        if (_this.status === "pending") {
            _this.status = "rejected"; // 状态变成失败
            _this.errReason = reason;
            _this.onRejectedCallbacks.forEach(fn=>fn())
        }
    }
    executor(resolve, reject);
}

// 定义then方法
Promise.prototype.then = function (onFulfilled, onRejected) {
    let _this = this;
    // 当resolve再同步代码块中
    if (_this.status === "fulfilled") {
        onFulfilled(_this.value)
    }
    // 当reject再同步代码块中
    if (_this.status === "rejected") {
        onRejected(_this.reason)
    }
    // 当resolve或者reject异步执行的时候
    if (_this.status === "pending") {
    	// 将成功回调函数放入成功数组中
        _this.onResolvedCallbacks.push(function () {
            onFulfilled(_this.value)
        })
        // 将失败回调函数放入失败数组中
        _this.onRejectedCallbacks.push(function () {
            onRejected(_this.reason)
        })
    }
}

module.exports = Promise

三、测试

	let Promise = require('./promise3')

	let p = new Promise((resolve, reject) => {
	    setTimeout(() => {
	        resolve("7777");
	        // reject("卧槽,失败了");
	    })
		console.log("ok");
		
	});
	p.then((data) => {
	    console.log(data); // 成功打印7777
	}, (error) => {
	    console.log(error);
	})

四、新的问题

这个时候虽然解决了异步调用的问题,但是此时链式调用会出问题,直接报错,比如

	p.then((data) => {
	    console.log(data);
	}, (error) => {
	    console.log(error);
	}).then((data2) => {
		console.log(data2);
	},(error2) => {
		console.log(error2);
	})

下一篇优化代码,使其支持链式调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值