zoukankan      html  css  js  c++  java
  • promise简单实现

    function isFunction(fn){
        return Object.prototype.toString.call(fn) === '[object Function]';
    }
    
    let ST = {
        pending: 0,
        resolved: 1,
        rejected: 2
    }
    
    function Promise(fn){
        let self = this;
        self.status = ST.pending;
        self.value = '';
        self.reason = '';
        self.resolveFns = [];
        self.rejectFns = [];
    
        //setTimeout延迟执行,将reslove执行放在下个循环,保证后续then方法先于它执行,不会出现前面已经resolve了,后面的then还没push进resolveFns数组
        function resolve(val){
            setTimeout(() => {
                if(self.status == ST.pending){
                    self.status = ST.resolved;
                    self.value = val;
                    //用数组保存回调,是为了处理一个promise挂载多个then的情况
                    //注意不是链式,这种场景很少出现
                    /*
                    形如:
                    promise.then(resolve1,reject1)
                    promise.then(resolve2,reject2)
                    promise.then(resolve3,reject3)
                    */
                    //在链式调用中,该数组通常只会有一个项,就是当前promise的下一个then里面的resolve函数
                    //且每次执行,通常都是一个新Promise的resolve数组
                    self.resolveFns.forEach(fn => fn());
                }
            })
        }
    
        function reject(val){
            setTimeout(() => {
                if(self.status == ST.pending){
                    self.status = ST.rejected;
                    self.reason = val;
                    self.rejectFns.forEach(fn => fn());
                }
            })
        }
    
        //执行出问题,直接reject,Promise的错误默认不会抛出到全局
        try{
            fn(resolve,reject);
        }
        catch(err){
            reject(err);
        }
    }
    
    Promise.prototype.then = function(onResolve,onReject){
        let self = this;
    
        //then每次执行都返回一个新的Promise,then方法要处理前一个promise的三种状态
        return new Promise(function(resolve,reject){
            function handle(value,thenFn){
                let res = isFunction(thenFn) && thenFn(value) || value;
                if(res instanceof Promise){
                    res.then(resolve,reject);
                }
                else{
                    resolve(res);
                }
            }
        
            //处理三种状态
            //fn函数体里,如果有错误; 会执行try catch里的 reject方法,执行then this.state就是rejected
            //如果没错误且没异步,resolve this.state就是resolved
            //如果没错误且有异步,this.state就是pending
            if(self.status == ST.pending){
                self.resolveFns.push(resloveHandle);
                self.rejectFns.push(rejectHandle);
            }
            else if(self.status == ST.resolved){
                self.handle(self.value,onResolve);
            }
            else if(this.status == ST.rejected){
                self.handle(self.reason,onReject);
            }
        })
    }
    
    Promise.prototype.catch = function(onReject){
        return this.then(undefined, onReject);
    }
    
    //finally不是promise的末尾,后面还可以有then,所以value和reason必须可以向下传递
    Promise.prototype.finally = function(fn){
        let P = this.constructor;
        return this.then(
            value => P.resolve(fn()).then(() => value),
            reason => P.resolve(fn()).then(() => throw reason);
        )
    }
    
    //done作为promise的末尾,用于收集所有可能的报错,catch方法捕捉所有错误,并抛出
    Promise.prototype.done = function(resolve,reject){
        return this.then(resolve, reject).catch(function(reason){
            setTimeout(function(){
                throw reason;
            });
        })
    }
    
    Promise.resolve = function(val){
        return new Promise((resolve) => {
            resolve(val);
        })
    }
    
    Promise.reject = function(val){
        return new Promise((resolve,reject) => {
            reject(val);
        })
    }
    
    Promise.race = function(promises){
        let len = promises.length;
        
        return new Promise(function(resolve,reject){
            while(len--){
                promises[len].then(resolve,reject);
            }
        })
    }
    
    Promise.all = function(promises){
        let len = promises.length,
            results = [];
    
        return new Promise(function(resolve,reject){
            //用一个数组收集单个promise执行后的结果,收集满数组所有结果,便是所有执行成功
            function reslove(index){
                return function(value){
                    results[index] = value;
                    if(results.length == len){
                        reslove(results);
                    }
                }
            }
    
            while(len--){
                promises[len].then(resolve(len),reject);
            }
        })
    }

  • 相关阅读:
    移动端 提交按钮呗软键盘挤上去的问题解决
    jenkins创建项目API踩坑记
    backstage使用笔记(2)- 跨域代理设置
    backstage使用笔记(1)- 项目的搭建和插件的创建
    什么是强缓存,什么是协商缓存?
    关于antd英文文案切换为中文
    记解决遇到自己电脑看线上项目没问题,别的同事电脑看线上项目有问题的疑难杂症
    vue.js组件传值
    Vue.js组件
    关于Object.keys()和for in的区别
  • 原文地址:https://www.cnblogs.com/mengff/p/11740638.html
Copyright © 2011-2022 走看看