• promise


      1 /*
      2 尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
      3 */
      4 
      5 
      6 // 定义三个状态
      7 const PENDING = "PENDING";
      8 const RESOLVED = "RESOLVED";
      9 const REJECTED = 'REJECTED';
     10 function resolvePromise(x, promise2, resolve, reject) {
     11   //判断x === promise, 抛出类型错误
     12   if (x === promise2) {
     13     console.log('======')
     14     return reject(new TypeError('类型错误'))
     15   }
     16   // 允许状态改变一次
     17   let called = false;
     18 
     19 
     20 
     21   try {
     22     //判断x是否包含then属性,thenable
     23     if (typeof x === 'object' && x !== null) {
     24       const then = x.then;
     25       if (typeof then === "function") {
     26         // console.log(typeof then)
     27         then.call(x, v => {
     28           if (called) return;
     29           called = true;
     30           resolvePromise(v, promise2, resolve, reject)
     31         }, r => {
     32           if (called) return;
     33           called = true;
     34           reject(r)
     35         })
     36       } else {
     37         if (called) return;
     38         called = true;
     39         resolve(x)
     40       }
     41     } else {
     42       if (called) return;
     43       called = true;
     44       resolve(x)
     45     }
     46   } catch (e) {
     47     if (called) return;
     48     called = true;
     49     reject(e)
     50   }
     51 }
     52 class Promise {
     53   constructor(exectuor) {
     54     try {
     55       //捕获执行器错误
     56       exectuor(this.resolve, this.reject)
     57     } catch (e) {
     58       this.reject(e)
     59     }
     60   }
     61 
     62   status = PENDING;
     63   value = null;
     64   reason = null;
     65   //存储失败和成功的回调
     66   onFullFilledCallbacks = [];
     67   onRejectedCallbacks = [];
     68 
     69   static all (args) {
     70     return new Promise((resolve, reject) => {
     71       args.reduce((prev, curr, i, arr) => {
     72         if (curr instanceof Promise) {
     73           curr.then((v) => {
     74             prev[i] = v;
     75             if (prev.length === arr.length) {
     76               resolve(prev)
     77             }
     78           }, r=> {
     79             reject(r)
     80           })
     81         } else {
     82           prev[i] = curr;
     83         }
     84         return prev;
     85       }, [])
     86     })
     87   }
     88   static resolve (v) {
     89     if (v instanceof  Promise) return v;
     90     return new Promise((resolve ,reject) => resolve(v));
     91   }
     92   static reject(r) {
     93     return new Promise((resolve,reject)=>{
     94       reject(r)
     95     })
     96   }
     97   static allSettled (args) {
     98     return new Promise((resolve, reject) => {
     99       function addData(prev, index, value){
    100         prev[index] = value;
    101         if (prev.length === args.length) {
    102           resolve(prev)
    103         }
    104       }
    105       args.reduce((prev, curr, index, arr) => {
    106         if (curr instanceof Promise) {
    107           curr.then(res => {
    108             addData(prev, index, {
    109               value: res,
    110               status: 'fulfilled'
    111             })
    112           }, r => {
    113             addData(prev, index, {
    114               reason: r,
    115               status: 'rejected'
    116             })
    117           })
    118         } else {
    119           addData(prev, index, {
    120             reason: curr,
    121             status: 'fulfilled'
    122           })
    123         }
    124       })
    125     })
    126   }
    127 
    128   static race(args) {
    129     return new Promise((resolve, reject) => {
    130       args.forEach((item) => {
    131         if (item instanceof Promise) {
    132           item.then(v => {
    133             resolve(v)
    134           }, r => {
    135             reject(r)
    136           })
    137         } else {
    138           resolve(item)
    139         }
    140       })
    141     })
    142   }
    143 
    144   finally (cb) {
    145     return this.then(v => {
    146       return Promise.resolve(cb()).then(() => v);
    147     }, r => {
    148       return Promise.resolve(cb()).then(() => { throw r })
    149     })
    150   }
    151 
    152   resolve = (v) => {
    153 
    154     //只有状态为pending才执行
    155     if (this.status === PENDING) {
    156       this.status = RESOLVED;
    157       this.value = v;
    158       this.onFullFilledCallbacks.forEach(c => c())
    159     }
    160   }
    161 
    162   reject = (r) => {
    163     if (this.status === PENDING) {
    164       this.status = REJECTED;
    165       this.reason = r;
    166       this.onRejectedCallbacks.forEach(c => c())
    167     }
    168   }
    169 
    170   then(onFullFilled, onRejected) {
    171     //onFullFilled onRejected类型判断
    172     if (typeof onFullFilled !== 'function') onFullFilled = v => v;
    173     if (typeof onFullFilled !== 'function') {
    174       onRejected = r => {
    175         throw r;
    176       }
    177     }
    178     const promise2 = new Promise((resolve, reject) => {
    179       if (this.status === RESOLVED) {
    180         // Promise为微任务,所以放到微任务队列执行
    181         queueMicrotask(() => {
    182           try {
    183             const x = onFullFilled(this.value);
    184             resolvePromise(x, promise2, resolve, reject)
    185           } catch (e) {
    186             reject(e)
    187           }
    188         })
    189       }
    190 
    191       if (this.status === REJECTED) {
    192         queueMicrotask(() => {
    193           try {
    194             const x = onRejected(this.reason)
    195             resolvePromise(x, promise2, resolve, reject)
    196           } catch (e) {
    197             reject(e)
    198           }
    199         })
    200       }
    201 
    202       if (this.status === PENDING) {
    203         //如果状态为pending,则执行方法放入数组中,等待resolve或reject时候执行
    204         this.onFullFilledCallbacks.push(() => {
    205           queueMicrotask(() => {
    206             try {
    207               const x = onFullFilled(this.value);
    208               resolvePromise(x, promise2, resolve, reject)
    209             } catch (e) {
    210               reject(e)
    211             }
    212           })
    213         })
    214 
    215         this.onRejectedCallbacks.push(() => {
    216           queueMicrotask(() => {
    217             try {
    218               const x = onRejected(this.reason);
    219               resolvePromise(x, promise2, resolve, reject)
    220             } catch (e) {
    221               reject(e)
    222             }
    223           })
    224         })
    225       }
    226     })
    227     return promise2;
    228   }
    229 }
    230 
    231 Promise.deferred = function() {
    232   var result = {};
    233   result.promise = new Promise(function(resolve, reject){
    234     result.resolve = resolve;
    235     result.reject = reject;
    236   });
    237 
    238   return result;
    239 }
    240 
    241 module.exports = Promise;
  • 相关阅读:
    在PHP语言中使用JSON
    PHP数组和Json之间的转换
    Mentohust 安装(win7环境)
    PHP采集网页图片并保存至本地
    php 操作数组 (合并,拆分,追加,查找,删除等)
    GitHub的使用
    【word】含章节号的题注编号以阿拉伯数字显示
    【转载】Mozilla5.0的含义
    同一服务器部署多个Tomcat时的端口号修改详情(同时启动两个Tomcat)
    Android Studio配置
  • 原文地址:https://www.cnblogs.com/ndh074512/p/14951622.html
Copyright © 2020-2023  润新知