记一次手写Promise

记第一次手写Promise

之前做项目的时候,一般使用AJAX请求数据,相信大多数同学都会使用.then来处理一些异步任务,但是这样的话可能会发生回调地狱,脑子混乱… 直到有一天,我看到了这段代码

function asyncFn1() {
  console.log('asyncFn1 run');
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('asyncFn1执行完了');
    }, 2000)
  })
}

function asyncFn2() {
  console.log('asyncFn2 run');
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('asyncFn2执行完了');
    }, 1000)
  })
}

function normalFn3() {
  console.log('normalFn3 run');
}

// 这样就比较好理解了,当asyncFn1re的resolve()执行的时候,才会执行.then()里面的函数,同理
asyncFn1().then(asyncFn2).then(normalFn3);

(可能是为了更好的链式使用.then,所以一般都使用函数返回一个Promise,而不是直接声明Promise???)

不管怎么说,我们今天就是要手写一个Promise,准备好了吗?

我们首先来看Promise的正常使用方法
// Promise在创建的时候,接收一个函数对象(被称为excutor),这个函数有两个参数
let p = new Promise((resolve, reject) => {
  console.log('这个函数是立即执行的');
  setTimeout(() => {
    resolve('异步操作得到的数据') // 可以把这里换成reject(’失败‘)试试	
  }, 1)    
})

// Promise的实例还有一个then方法,也接收两个参数,第一个参数为’成功时的回调‘,第二个参数为’失败时的回调‘
p.then((data) => {
    console.log('success:',data);
}, (data) => {
    console.log('eorr:',data);
})

当resolve()方法被执行的时候,就会执行then中的第一个函数,当reject()方法被执行的时候,就会执行then中的第二个函数

现在,我们尝试着自己实现一个Promise,暂且称为MyPromise
// 还是使用ES5的语法来写
// 刚刚上文中提到,我们在new Promise的时候,传入一个function对象,称之为excutor
function MyPromise(excutor) {
    var self = this;
    self.resolve = '';
    self.reject = '';
    self.value = '';
    self.reason = '';
    self.onResolvedCallbacks = [];
    self.onRejectedCallbacks = [];
    // 3.这里有一个隐藏的知识点,new Promise创建的实例有一个默认的状态 --- ‘pending’,只有在resovle或者reject的时候才会改变这个状态,且改变之后不能创新修改
    function resolve(value1) {
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value1;
            self.onResolvedCallbacks.forEach((callback) => {
                callback()
            })
        }
    }
    
    function reject(value2) {
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = value2;
            self.onRejectedCallbacks.forEach((callback) => {
                callback()
            })
        }
    }
    excutor(resolve, reject); // 1.传进来的这个excutor是立即执行的
}
// 2.刚刚上文中明显可以看到,Promise的实例p,有一个then方法,且接收两个参数,分别是'成功回调','失败回调'
MyPromise.prototype.then = (resolve, reject) => {
    let self = this;
    if (self.status === 'resovled')
        // 4. 我们会更具Promise的状态值去决定调用then中的第一个,还是第二个函数,并且赋值 
        resolve(self.value1);
    }
    if (self.status === 'rejected') {
        reject(self.value2);
    }
	// 5.执行的时候,发现,有两个问题 1.异步调用顺序不正确 2.多次使用.then(不是链式)的时候会有问题
	// 所以,我们肯定在将多次的then里面要做的事情,在'pending'状态下,先放在数据中先存储起来,等'resolve'的时候,再调用
 	if (self.status === 'pending') {
        self.onResolvedCallbacks.push(() => resolve(self.value));
        self.onRejectedCallbacks.push(() => resolve(self.reason));
    }
}

写到这里,应该足够理解Promise的原理了,但是现在还是是存在一些问题的,比如,Promise的链式调用,我们目前还没有实现的,就是文章首页的那种写法,但是个人不是很喜欢这样的写法,之后在开发中可能会多尝试一下 async await的开发方式(听说很香,也很容易从字面上理解)

function asyncFn1(){
    console.log('asyncFn1');
    return new Promise(function(resolve){
        setTimeout(function(){
            resolve('123');
        }, 2000)
    })
}

function asyncFn2() {
    console.log('asyncFn2');
    return new Promise(function(resolve){
        setTimeout(function(){
            resolve('456');
        }, 2000)
    })
}

async function asyncFn () {
    var a = await asyncFn1();
    var b = await asyncFn2();

    console.log(a,b)
}

asyncFn();

详情可以参考:https://www.jianshu.com/p/b4fd76c61dc9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值