站点工具

用户工具


====== 差别 ======

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
javascript_手写promise [2022/03/18 16:04]
若愚
javascript_手写promise [2022/04/06 22:33] (当前版本)
若愚
行 1: 行 1:
 # 手写Promise # 手写Promise
-代码比较短的实现+
  
 ```javascript ```javascript
-/** +const PENDING = "PENDING"; 
- * 1. new Promise时,需要传递一个 executor 执行器,执行器立刻执行 +const FULFILLED = "FULFILLED"; 
- * 2. executor 接受两个参数,分别是 resolve 和 reject +const REJECTED = "REJECTED";
- * 3. promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled +
- * 4. promise 的状态一旦确认,就不会再改变 +
- * 5. promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled,  +
-      和 promise 失败的回调 onRejected +
- * 6. 如果调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值作为参数传递进去。 +
-      如果promise已经失败,那么执行 onRejected, 并将 promise 失败的原因作为参数传递进去。 +
-      如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(发布订阅) +
- * 7. then 的参数 onFulfilled 和 onRejected 可以缺省 +
- * 8. promise 可以then多次,promise 的then 方法返回一个 promise +
- * 9. 如果 then 返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功的回调(onFulfilled) +
- * 10. 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调(onRejected) +
- * 11.如果 then 返回的是一个promise,那么会等这个promise执行完,promise如果成功, +
-   就走下一个then的成功,如果失败,就走下一个then的失败 +
- */+
  
-const PENDING = 'pending'; +function resolve(value) { 
-const FULFILLED = 'fulfilled'; +  return value
-const REJECTED = 'rejected'; +}
-function Promise2(executor) { +
-  let self = this+
-  self.status = PENDING; +
-  self.onFulfilled = []; +
-  self.onRejected = [];+
  
-  function resolve(value) { +function reject(err) { 
-    if (self.status === PENDING) { +  throw err
-      self.status = FULFILLED+}
-      self.value = value; +
-      self.onFulfilled.forEach(fn => fn()); +
-    } +
-  }+
  
-  function reject(reason) { +function resolvePromise(promise2, x, resolve, reject) { 
-    if (self.status === PENDING) { +  if (promise2 === x) { 
-      self.status = REJECTED; +    return reject( 
-      self.reason = reason; +      new TypeError("Chaining cycle detected for promise #<Promise>") 
-      self.onRejected.forEach(fn =fn());+    );
   }   }
- +  let called; 
-  try +  if ((typeof x === "object" && x != null) || typeof x === "function"
-    executor(resolve, reject); +    try { 
-  } catch (e) { +      let then = x.then; 
-    reject(e);+      if (typeof then === "function") { 
 +        then.call( 
 +          x, 
 +          (y) => { 
 +            if (called) return; 
 +            called = true; 
 +            resolvePromise(promise2, y, resolve, reject); 
 +          }, 
 +          (r) => { 
 +            if (called) return; 
 +            called = true; 
 +            reject(r); 
 +          } 
 +        ); 
 +      } else { 
 +        resolve(x); 
 +      } 
 +    } catch (e) { 
 +      if (called) return; 
 +      called = true; 
 +      reject(e); 
 +    } 
 +  } else { 
 +    resolve(x);
   }   }
 } }
  
-Promise2.prototype.then = function (onFulfilled, onRejected) { +class Promise { 
-  onFulfilled typeof onFulfilled === 'function' ? onFulfilled : value => value+  constructor(executor) { 
-  onRejected typeof onRejected === 'function' ? onRejected : reason =throw reason }+    this.status PENDING; 
-  let self = this; +    this.value undefined; 
-  let promise2 new Promise2((resolve, reject) => { +    this.reason undefined; 
-    if (self.status === FULFILLED) {+    this.resolveCallbacks []; 
 +    this.rejectCallbacks []
 + 
 +    let resolve (value) => { 
 +      if (this.status === PENDING) { 
 +        this.status = FULFILLED
 +        this.value value; 
 +        this.resolveCallbacks.forEach((fn) => fn())
 +      } 
 +    }; 
 + 
 +    let reject = (reason) => { 
 +      if (this.status === PENDING) { 
 +        this.status = REJECTED; 
 +        this.reason = reason; 
 +        this.rejectCallbacks.forEach((fn) => fn()); 
 +      } 
 +    }; 
 + 
 +    try { 
 +      executor(resolve, reject); 
 +    } catch (error) { 
 +      reject(error); 
 +    } 
 +  }
  
-      setTimeout(() => +  then(onFulfilled, onRejected) { 
-        try { +    onFulfilled typeof onFulfilled === "function" ? onFulfilled : resolve; 
-          let x = onFulfilled(self.value); +    onRejected typeof onRejected === "function" ? onRejected : reject; 
-          resolvePromise(promise2, x, resolve, reject); +    let promise2 new Promise((resolve, reject) => 
-        } catch (e) { +      if (this.status === FULFILLED) {
-          reject(e); +
-        } +
-      })+
-    } else if (self.status === REJECTED) { +
-      setTimeout(() => { +
-        try { +
-          let onRejected(self.reason); +
-          resolvePromise(promise2, x, resolve, reject)+
-        } catch (e) { +
-          reject(e); +
-        } +
-      }); +
-    } else if (self.status === PENDING+
-      self.onFulfilled.push(() => {+
         setTimeout(() => {         setTimeout(() => {
           try {           try {
-            let x = onFulfilled(self.value);+            let x = onFulfilled(this.value);
             resolvePromise(promise2, x, resolve, reject);             resolvePromise(promise2, x, resolve, reject);
           } catch (e) {           } catch (e) {
             reject(e);             reject(e);
           }           }
-        }); +        }, 0); 
-      }); +      } 
-      self.onRejected.push((=> {+ 
 +      if (this.status === REJECTED) {
         setTimeout(() => {         setTimeout(() => {
           try {           try {
-            let x = onRejected(self.reason);+            let x = onRejected(this.reason);
             resolvePromise(promise2, x, resolve, reject);             resolvePromise(promise2, x, resolve, reject);
           } catch (e) {           } catch (e) {
             reject(e);             reject(e);
           }           }
-        }); +        }, 0); 
-      }); +      }
-    } +
-  }); +
-  return promise2; +
-}+
  
-function resolvePromise(promise2, x, resolve, reject) { +      if (this.status === PENDING) { 
-  let self = this+        this.resolveCallbacks.push(() => { 
-  if (promise2 === x) { +          setTimeout(() =
-    reject(new TypeError('Chaining cycle')); +            try { 
-  } +              let onFulfilled(this.value); 
-  if (x && typeof x === 'object' || typeof x === 'function'+              resolvePromise(promise2, x, resolve, reject); 
-    let used; //PromiseA+2.3.3.3.3 只能调用一次 +            catch (e) { 
-    try { +              reject(e); 
-      let then x.then; +            } 
-      if (typeof then === 'function') { +          }, 0);
-        then.call(x, (y=> { +
-          if (used) return+
-          used = true; +
-          resolvePromise(promise2, y, resolve, reject); +
-        }(r=> +
-          if (usedreturn+
-          used = true; +
-          reject(r);+
         });         });
  
-      }else+        this.rejectCallbacks.push(() => 
-        if (usedreturn; +          setTimeout(() => { 
-        used true+            try { 
-        resolve(x);+              let x onRejected(this.reason)
 +              resolvePromise(promise2, x, resolve, reject); 
 +            } catch (e) { 
 +              reject(e); 
 +            } 
 +          }, 0); 
 +        });
       }       }
-    } catch (e+    }); 
-      if (used) return+ 
-      used = true; +    return promise2;
-      reject(e); +
-    +
-  } else { +
-    resolve(x);+
   }   }
 } }
 +```
  
 +更标准的实现
  
 +https://github.com/taylorhakes/promise-polyfill
  
  
- 
-var p1 = new Promise2((r, j) => { 
-  console.log('a'); 
-  setTimeout(()=> { 
-    r(1) 
-  }, 1000) 
-}) 
-console.log(p1) 
-var p2 = p1.then(v => { 
-  console.log('b') 
-  console.log(v+1) 
-  return v+1 
-}) 
-console.log(p2) 
-var p3 = p2.then(v => { 
-  console.log('c') 
-  console.log(v+1) 
-}) 
-console.log(p3) 
-``` 
- 
-在控制台 查看 p1, p2, p3的值 
- 
-## 来源 
--[Promise的源码实现(完美符合Promise/A+规范)](https://juejin.cn/post/6844903796129136654) 
  
若愚 · 2022/03/18 16:04 · javascript_手写promise.1647590660.txt.gz