2.3.JavaScript异步流程控制- Promise源码

237 阅读5分钟

Promises/A+规范 英文 Promises/A+规范 中文

Promise使用

// 同一个promise可以then多次
let p = new Promise(function (resolve, reject) {
	resolve('xx')
})
p.then(function (data) {
	console.log('success', data)
}, function (err) {
	console.log(err);
});

Promise源码解析

Promise源码(一)

  • Promise状态: pending, fulfilled 或 rejected.
  • then 方法

case.js

let Promise = require('./promise');
let p = new Promise(function (resolve, reject) {
  resolve('xxx');
})
// 同一个Promise可以then多次
p.then(function (data) {
  console.log(`success ${data}`);
}, function (err) {
  console.log(`err ${err}`);
})

promise.js


function Promise(executor) {
  let self = this;
  // 保存Promise状态,默认pending;三个状态: pending, fulfilled 或 rejected.
  self.status = 'pending';
  // 保存成功的值
  self.value = undefined;
  // 保存失败的原因
  self.reason = undefined;
  // 只有Promise状态为pending才能进行转化
  function resolve(value) {
    if (self.status === 'pending') {
      self.value = value;
      self.status = 'fulfilled';
    }
  }
  function reject(reason) {
    if (self.status === 'pending') {
      self.reason = reason;
      self.status = 'rejected';
    }
  }
  try {
    executor(resolve, reject); // 跑出异常时,走下一个then的失败
  } catch (e) {
    reject(e); // 出错,reason就是原因
  }
}
Promise.prototype.then = function (onFulFilled, onRejected) {
  let self = this;
  if (self.status === 'fulfilled') {
    onFulFilled(self.value);
  }
  if (self.status === 'rejected') {
    onRejected(self.reason);
  }
}

module.exports = Promise;

Promise源码(二)

  • 执行器中有异步代码时

case.js

let Promise = require('./promise');
let p = new Promise(function (resolve, reject) {
  setTimeout(() => {
    resolve('延迟1秒');
  }, 1000)
})
// 同一个Promise可以then多次
p.then(function (data) {
  console.log(`success ${data}`);
}, function (err) {
  console.log(`err ${err}`);
})

promise.js

function Promise(executor) {
  let self = this;
  // 保存Promise状态,默认pending;三个状态: pending, fulfilled 或 rejected.
  self.status = 'pending';
  // 保存成功的值
  self.value = undefined;
  // 保存失败的原因
  self.reason = undefined;
  // 异步方法存起来
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];

  // 只有Promise状态为pending才能进行转化
  function resolve(value) {
    if (self.status === 'pending') {
      self.value = value;
      self.status = 'fulfilled';
      // fulfilled执行异步的方法
      self.onResolvedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  function reject(reason) {
    if (self.status === 'pending') {
      self.reason = reason;
      self.status = 'rejected';
      // rejected执行异步的方法
      self.onRejectedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  try {
    executor(resolve, reject); // 跑出异常时,走下一个then的失败
  } catch (e) {
    reject(e); // 出错,reason就是原因
  }
}
Promise.prototype.then = function (onFulFilled, onRejected) {
  let self = this;
  // 成功后执行onFulFilled返回值
  if (self.status === 'fulfilled') {
    onFulFilled(self.value);
  }
  // 失败后执行onRejected返回原因
  if (self.status === 'rejected') {
    onRejected(self.reason);
  }
  // 当Promise的executor中有异步方法时
  if (self.status === 'pending') {
    self.onResolvedCallbacks.push(function () {
      onFulFilled(self.value);
    })
    self.onRejectedCallbacks.push(function () {
      onRejected(self.reason);
    })
  }
}

module.exports = Promise;

Promise源码(三)

  • 链式调用
    • Promise 中每次调用 then 都应该返回一个新的 Promise。
    • Promise 的实例只能成功或者失败,不能既成功又失败。
    • promise2

case.js

let Promise = require('./promise');
let p = new Promise(function (resolve, reject) {
  resolve('xxx');
})
p.then(function (data) {
  console.log(`success ${data}`);
}, function (err) {
  console.log(`err ${err}`);
}).then(function (data) {
  console.log(`success ${data}`);
}, function (err) {
  console.log(`err ${err}`);
})

promise.js

function Promise(executor) {
  let self = this;
  // 保存Promise状态,默认pending;三个状态: pending, fulfilled 或 rejected.
  self.status = 'pending';
  // 保存成功的值
  self.value = undefined;
  // 保存失败的原因
  self.reason = undefined;
  // 异步方法存起来
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];

  // 只有Promise状态为pending才能进行转化
  function resolve(value) {
    if (self.status === 'pending') {
      self.value = value;
      self.status = 'fulfilled';
      // fulfilled执行异步的方法
      self.onResolvedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  function reject(reason) {
    if (self.status === 'pending') {
      self.reason = reason;
      self.status = 'rejected';
      // rejected执行异步的方法
      self.onRejectedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  try {
    executor(resolve, reject); // 跑出异常时,走下一个then的失败
  } catch (e) {
    reject(e); // 出错,reason就是原因
  }
}
// 核心方法:处理成功或失败执行的返回值,处理promise2的关系;
function resolvePromise(promise2, x, resolve, reject) {

}
Promise.prototype.then = function (onFulFilled, onRejected) {
  let self = this;
  let promise2;
  promise2 = new Promise(function (resolve, reject) {
    // 成功后执行onFulFilled返回值
    if (self.status === 'fulfilled') {
      setTimeout(() => {
        try {
          // 限制需要做的事情就是把then中成功或者失败后执行的结果获取到
          // 判断是否为promise,是promise就让promise执行,取到这个promise的执行结果。
          let x = onFulFilled(self.value);
          // 判断promise2和x也是then函数返回的结果和promise2的关系,如果x是普通值,让promise2成功;如果是一个失败的promise,直接让promise2失败
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0)
    }
    // 失败后执行onRejected返回原因
    if (self.status === 'rejected') {
      setTimeout(() => {
        try {
          let x = onRejected(self.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0)
    }
    // 当Promise的executor中有异步方法时
    if (self.status === 'pending') {
      self.onResolvedCallbacks.push(function () {
        setTimeout(() => {
          try {
            let x = onFulFilled(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0)
      })
      self.onRejectedCallbacks.push(function () {
        setTimeout(() => {
          try {
            let x = onRejected(self.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0)
      })
    }
  })
  // 调用then后返回一个Promise
  return promise2;
}
module.exports = Promise;

Promise源码(四)

  • Promise核心方法:处理成功或失败执行的返回值,处理promise2的关系;
  • resolvePromise

case.js

let Promise = require('./promise');
let p = new Promise(function (resolve, reject) {
  resolve();
})
p.then(function (data) {
  // 判断返回的是一个Promise
  return new Promise((resolve, reject) => {
    resolve(1000);
  })
}).then(data => {
  console.log(`success ${data}`);
}, err => {
  console.log(`err ${err}`)
})

promise.js

function Promise(executor) {
  let self = this;
  // 保存Promise状态,默认pending;三个状态: pending, fulfilled 或 rejected.
  self.status = 'pending';
  // 保存成功的值
  self.value = undefined;
  // 保存失败的原因
  self.reason = undefined;
  // 异步方法存起来
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];

  // 只有Promise状态为pending才能进行转化
  function resolve(value) {
    if (self.status === 'pending') {
      self.value = value;
      self.status = 'fulfilled';
      // fulfilled执行异步的方法
      self.onResolvedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  function reject(reason) {
    if (self.status === 'pending') {
      self.reason = reason;
      self.status = 'rejected';
      // rejected执行异步的方法
      self.onRejectedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  try {
    executor(resolve, reject); // 跑出异常时,走下一个then的失败
  } catch (e) {
    reject(e); // 出错,reason就是原因
  }
}
// 核心方法:处理成功或失败执行的返回值,处理promise2的关系;
function resolvePromise(promise2, x, resolve, reject) {
  // 有可能x===promise2
  if (promise2 === x) {
    return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'));
  }
  // 如果是第三方的Promise
  let called; // 文档要求,一旦成功,不能调用失败
  if ((x !== null && typeof x === 'object') || typeof x === 'function') {
    // x可能是一个promise
    try {
      // x = {then:function(){}}
      let then = x.then; // 取then方法

      if (typeof then === 'function') {
        then.call(x, function (y) {
          if (!called) { called = true; } else { return; }
          resolvePromise(x, y, resolve, reject); // 递归检查promise
        }, function (r) {
          if (!called) { called = true; } else { return; }
          reject(r);
        });
      } else {
        resolve(x); // 普通值
      }
    } catch (error) {
      if (!called) { called = true; } else { return; }
      reject(error);
    }
  } else {
    // x是普通值,直接返回
    resolve(x);
  }
}
Promise.prototype.then = function (onFulFilled, onRejected) {
  // 判断onFulFilled和onRejected是函数
  onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : function (data) {
    return data;
  }
  onRejected = typeof onRejected === 'function' ? onRejected : function (err) {
    throw err;
  }
  let self = this;
  let promise2;
  promise2 = new Promise(function (resolve, reject) {
    // 成功后执行onFulFilled返回值
    if (self.status === 'fulfilled') {
      setTimeout(() => {
        try {
          // 限制需要做的事情就是把then中成功或者失败后执行的结果获取到
          // 判断是否为promise,是promise就让promise执行,取到这个promise的执行结果。
          let x = onFulFilled(self.value);
          // 判断promise2和x也是then函数返回的结果和promise2的关系,如果x是普通值,让promise2成功;如果是一个失败的promise,直接让promise2失败
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0)
    }
    // 失败后执行onRejected返回原因
    if (self.status === 'rejected') {
      setTimeout(() => {
        try {
          let x = onRejected(self.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0)
    }
    // 当Promise的executor中有异步方法时
    if (self.status === 'pending') {
      self.onResolvedCallbacks.push(function () {
        setTimeout(() => {
          try {
            let x = onFulFilled(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0)
      })
      self.onRejectedCallbacks.push(function () {
        setTimeout(() => {
          try {
            let x = onRejected(self.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0)
      })
    }
  })
  // 调用then后返回一个Promise
  return promise2;
}
// 测试是否符合PromiseA+规范 cnpm i promises-aplus-tests -g
Promise.deferred = Promise.defer = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd;
}
module.exports = Promise;