浅谈JavaScript的promise对象

106 阅读2分钟

promise对象是es6的新增的,在自建promise对象时,回调往往都有 resolve 和 reject 形参,分别表示执行成功和失败的需要返回的信息:

 // 声明一个promise对象
 let p = new Promise((resolve, reject) => {
  let a = 1 + 1;
  if (a == 2) {
      resolve('success')
  } else {
      reject('failed')
}
// 使用promise对象  
// then 代表执行 resolve 时的回调
// catch 代表执行 reject 时的回调
  p.then((message) => {
    consolve.log(message); 
  }).catch(message => {
    consolve.log(message);  
  })
 })

promise 除了作为构造函数生成 promise 实例外,其原型下还有 all 、race 方法:

const a = new promise((resolve, reject) => {
    resolve('a')
})
const b = new promise((resolve, reject) => {
    resolve('b')
})
const c = new promise((resolve, reject) => {
    resolve('c')
})
// all
Promise.all([
  a,
  b,
  c
]).then((message) => {//等待所有a b c promise对象有执行结果后再执行此回调
  console.log(message);// 返回一个装有a b c promise对象 resolve 的数组
})
// race
Promise.race([
  a,
  b,
  c
]).then((message) => {//有执行结果后就执行此回调
  console.log(message);// 返回a b c promise对象最快执行完的 resolve
})

以上是 promise 的使用,接下来为了更深入的学习 promise 内部使用原理,我将大致模仿 promise 创建一个 myPromise 的原型:

function myPromise (fun) {
    // 状态
    this.status = "pending";
    // 回调传入的值,后期可以根据实例下的value获取
    this.value = undefined;
    
    // 成功时执行的函数
    let resolve = value => {
        this.status = "resolved";
        this.value = value;
        let p = this.successQueue[0](value);
        for (let i = 1; i < this.successQueue.length; i++) {
            p.then(this.successQueue[i], this.failedQueue[i]);
        }
    }
    // 失败时执行的函数
    let reject = value => {
        this.status = "rejected";
        this.value = value;
        this.failedQueue[0](value);
    }
    
    fun(resolve, reject);
    this.successQueue = [];
    this.failedQueue = [];
}

myPromise.prototype.then = function(successFun, failedFun) {
    this.successQueue.push(successFun); // 成功队列
    this.failedQueue.push(failedFun); // 失败队列
    return this; // 返回实例自己,用于能够进行链式调用 then
}

// 使用
// 传入 myPromise 这个回调就是 fun
let aa = new myPromise(function(resolve, reject) {
    setTimeout(function(){
       resolve(111);  
    }, 3000);
});

let bb = new myPromise(function(resolve, reject) {
    setTimeout(function(){
       resolve(222);  
    }, 3000);
});

aa.then(() => { // resolve 回调
    console.log("success1");
    return bb; // 返回 promise 对象才能进行下一步 then
}, () => { // reject 回调
    console.log("failed1")
}).then(() => {
    console.log("success2");
}, () => {
    console.log("failed2")
})

上诉代码执行过程: aa 对象会先执行两次 then 方法,在 aa myPromise 实例下的 successQueue 和 failedQueue 分别各自推入success1和success2的回调函数,然后执行 resolve(111),这时已执行 success1 回调且 aa 的 resolve 函数中的 p 变量将会是 success1 返回的 bb myPromise 实例,然后传入 success2 回调进入 bb myPromise 中,在 bb myPromise 实例下的 successQueue 和 failedQueue 分别各自只推入 success2 的回调函数,然后执行 resolve(222),这时已执行 success2 回调且 aa 的resolve 函数中的 p 变量因为 success2 回调函数没有 return 将会是 undefined,然后执行过程就完成了。 success1 和 success2 都是3秒后一起打印出来,success1 先,success2 后,但是没有像有些同学认为的先 3 秒再等 3 秒这种情况。