JavsScript系列-Promise的function写法

126 阅读1分钟

JavsScript系列-Promise的function写法

JS是单线程非阻塞的,解决非阻塞就需要通过回调来实现

Promise只是视觉上看起来是同步的,其实实现的本质依然是异步的,只是借助异步事件回调,通过then方法产生链式调用,看起来就是按顺序执行。

  • 在Promise的另一篇文章中,我们使用class的写法探究了Promise的原理,本文中,我们使用function的写法来实现一个简单的Promise

实现

// 定义一个Promise, 接收一个函数作为参数
function Promise(callbalk){
    this.state = 'pending' // Promise A+规范的三个状态:pending, resolved,rejected;
    this.data = null;      // Promise 维护一个data;
    this.onthen = [];       // then方法收集的回调队列;
    this.funIndex = 0;
    this.onReject = function(error) {
        throw error;
    }
    // 异步执行初始函数
    setTimeout(function() {
        callback && callback(this.resolve.bind(this), this.reject.bind(this));
    }.bind(this))
    
    return this;            // Promise返回其自身;以便找到then方法
}

由JS事件循环机制可以得知,then方法属于微任务,处于宏任务队列中,所以首次会先执行微任务,then方法内部将回调函数推入onthen数组中。

Promise.prototype.then = function(callback) {
    this.onthen.push(callback);
    return this;
}

同时,resolve方法需要在内部执行onthen中的方法,并继续返回当前Promise对象

Promise.prototype.resolve = function(data) { // data是异步执行完成后的数据
    this.state = 'resolved';
    this.data = data;
    
    setTimeout(function() {
        for(let i = this.funIndex, i < this.onthen.length; this.funIndex++){
            let callback = this.onthen.shift();
            this.data = callback(this.data); // resolve的返回值,保存在this.data中
        }
    }.bind(this))
    
    return this;
}

reject方法也需要返回当前的Promise对象,同时执行onReject函数,用于错误捕获

Promise.prototype.reject = function(error) {
    this.state = 'rejected';
    this.onReject(error);
    return this;
}

catch方法用来捕获错误,当错误被捕获时,Promise的状态应该被清零

Promise.prototype.catch = function(callback) {
    this.onthen = [];
    this.onReject = callback;
    return this;
}

测试

const p1 = new Promise(function (resolve, reject) {
​
   setTimeout(() => {
      resolve(1);       
   }, 1000);
});
​
p1.then((res) => {
  console.log(res);
  return 2;
})
  .then((res) => {
    console.log(res);
    return 3;
  })
  .then((res) => {
    console.log(res);
  });
​

\