(function () {
"use strict"
/* 核心代码 */
function Promise(executor) {
var self = this;
/* 1. 必须传executor函数 */
if(typeof executor !== 'function') throw new TypeError('Promise resolver executor is not a function');
/* 2. 必须通过new创建 */
// (new.target);//new.target存储new的那个构造函数 如果是当做普通函数执行,则值是undefined
if(!(self instanceof Promise)) throw new TypeError('undefined is not a Promise');
//new的过程
// 1.创建一个新对象
// 2.这个新对象内部的[[prototype]]指针被赋值为构造函数的prototype属性(构造函数的原型对象)
// 3.构造函数内部的this指向这个新对象(this指向新对象)
// 4.执行构造函数内部的代码(给新对象添加属性)
// 5.如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象
/* 给实例添加属性 */
//property
self.state = 'pending';
self.result = undefined;
// 为什么用数组 因为同一个实例可以多次.then() 不是链式调用 而是p.then() p.then()
// self.onfulfilledCallbacks = [];
// self.onrejectedCallbacks = [];
define(self,'onfulfilledCallbacks',[]);
define(self,'onrejectedCallbacks',[]);
/* 改变状态的函数 */
var change = function(state, result) {
// 状态已经改变之后,不再进行修改了
if(self.state !== 'pending') return;
self.state = state;
self.result = result;
//异步通知集合中的方法执行
var callbacks = state === "fulfilled"? self.onfulfilledCallbacks : self.onrejectedCallbacks;
if(callbacks.length > 0) {
// 用异步宏任务来模拟异步微任务 为什么这需要是异步的 异步通知集合中的方法执行
setTimeout(function() {
callbacks.forEach(function(callback){
callback(self.result);
})
})
}
}
/* 立即执行executor */
// try catch的目的 executor执行报错,状态直接改为reject 值为报错原因
try{
executor(
function resolve(value){
change('fulfilled', value);
},
function reject(reason){
change('rejected', reason);
}
);
}catch(err) {
change('rejected', err.message);
}
}
/* 处理THEN方法返回的新实例promise的状态和值 */
// 第一个参数 promise是.then返回的实例p2 resolve和reject是控制p2状态和值的
// x是onfullfilled或onrejected执行的返回结果
// x的值决定promise的状态和值
// onfullfilled或onrejected执行的返回结果决定promise的状态和值
var resolvePromise = function resolvePromise(promise,x,resolve,reject) {
if(x === promise) throw new TypeError('chaining cycle detected for promise #<promise>');
// onfullfilled或Onrejected执行的返回值x 是一个对象或者函数
if(x !== null && /^(object|function)$/.test(typeof x)){
// 去访问then
var then;
try{
// 获取then promise对象都有then
then = x.then;//如果做了get劫持 有可能访问then的时候报错
}catch(err){
reject(err);
return;
}
// 判断then方法是否为函数
if(typeof then === 'function') {
// 此时x可以认定为是一个promise的实例
// 如果then是一个函数 执行then 让里面的this为x
//检测then方法执行有没有报错
var called = false; // 同时只有一个处理
try{
then.call(
x,//这个x的成功和失败,决定了promise的成功和失败
// 怎么看x的成功和失败 执行x.then x成功执行onfullfilled方法 x失败执行onrejected
function onfulfilled(y) {
if(called) return;
called = true;
// 考虑到
//let p2 = Promise.resolve(10);
//let p2 = p1.then(() => {
// return Promise.resolve(Promise.reject(-1));
// });
// 重点!!
resolvePromise(promise,y,resolve,reject);
},
function onrejected(r) {
if(called) return;
called = true;
reject(r);//x是失败的 则让promise也变成是失败的
}
);
}catch(error){
if(called) return;
called = true;
//then方法执行有报错
reject(error);
}
return;
}
}
// 不是promise实例
resolve(x);
}
/* 写一个方法添加属性 */
var define = function(obj, key, value) {
Object.defineProperty(obj, key, {
enumerable: false,//内置属性中浅颜色的是不可枚举属性
// 设置成不可枚举的目的:防止for..in..把共用的属性也迭代到
writable: true,//能否重写的
configurable: true,//能否被删除
value: value,
});
}
/* 检测是否为Promise的实例 */
var checkInstance = function (self) {
if(!(self instanceof Promise)){
throw new TypeError('Method then called on incompatible reveiver #<Promise>');
}
}
var proto = Promise.prototype;
// Object.defineProperty(proto, 'then', {
// enumerable: false,//内置属性中浅颜色的是不可枚举属性
// writable: true,//能否重写的
// configurable: true,//能否被删除
// value: function() {
// }
// });
// 直接这么加是可枚举的
// proto.catch = function() {}
/* 原型对象 */
define(proto,Symbol.toStringTag, "Promise")
define(proto,'then', function then(onfulfilled, onrejected) {
// 为什么需要判断是否为promise实例呢 then只能通过实例调用 不能通过Promise.prototypr.then()调用
// Promise.then应该是异步微任务
checkInstance(this)
var self = this;
var promise;
/* 实现THEN的穿透机制 */
// 判断onfullfilled和onrejected有没有传
if(typeof onfulfilled !== 'function') {
onfulfilled = function(value) {
return value;
}
}
if(typeof onrejected !== 'function') {
onrejected = function(reason) {
throw reason;
}
}
/* 实现THEN链机制 */
//promise的状态最终由resolve和reject决定,返回的值由onfulfilled和onrejected的返回值决定,如果它俩执行的时候报错,promise的状态为reject
promise = new Promise(function(resolve, reject) {
switch (self.state) {
case 'fulfilled':
// queueMicrotask(()=>{})//创建异步微任务
// 用异步宏任务来模拟
setTimeout(function(){
try{
var x = onfulfilled(self.result);//x是返回值
//promise是返回的新实例 resolve reject改变新实例的状态
resolvePromise(promise, x, resolve, reject);
}catch(err) {
reject(err);
}
});
break;
case 'rejected':
setTimeout(function(){
try{
var x = onrejected(self.result);
resolvePromise(promise, x, resolve, reject);
}catch(err) {
reject(err);
}
})
break;
default:
// self.onfulfilledCallbacks.push(onrejected);
// self.onrejectedCallbacks.push(onrejected);
// 往集合中放一个匿名函数 结果是一样的 但是可以实现 onfullfilled执行放到当前上下中了?
//要在当前上下文执行才能拿到resolve和reject push了一个function
self.onfulfilledCallbacks.push(function(value){
try{
var x = onfulfilled(value);
resolvePromise(promise, x, resolve, reject);
}catch(err){
reject(err);
}
});
self.onrejectedCallbacks.push(function(value){
try{
var x = onrejected(value);
resolvePromise(promise, x, resolve, reject);
}catch(err){
reject(err);
}
});
// 把方法存储起来,在修改状态的时候,去通知执行
}
});
return promise;
});
define(proto,'catch', function catchMy(onrejected) {
checkInstance(this)
var self = this;
return self.then(null,onrejected);
});
/* 静态私有属性方法 */
define(Promise,'resolve', function resolve(value) {
return new Promise(function(resolve) {
resolve(value);
});
});
define(Promise,'reject', function reject(reason) {
return new Promise(function(_,reject) {
reject(reason);
});
})
// let p1 = new Promise((resolve, reject)=>{
// resolve(10);
// });
// /* let p2 = p1.then((value)=>{
// console.log('成功', value);
// return new Promise((_, reject)=>{
// reject(-1);
// })
// }, (reason)=>{
// console.log('失败', reason);
// }); */
// let p2 = p1.then(null);
// /*
// value => value p2状态为成功
// reason => throw reason p2状态为失败
// */
// p2.then((value)=>{
// console.log('成功', value);
// }, (reason)=>{
// console.log('失败', reason);
// });
/* 暴露API */
if(typeof window !== undefined) window.Promise = Promise;
if(typeof module === 'object' && typeof module.exports === 'object') module.exports = Promise;
})();
Promise手写
最新推荐文章于 2024-06-12 11:59:04 发布