最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手动实现Promise

    正文概述 掘金(奋斗--Lzk)   2021-02-21   563

    手动实现 Promise

    请以官方文档为准
    

    状态

    Promise 有三个状态,分别为:

    • pending 初始状态
    • fulfilled 成功状态
    • rejected 失败状态

    Promise 的只有在 pending 状态下,才能转更为其他状态,当状态变更后,无法再变更为其他状态。

    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    
    function MyPromise(excutor){
        // 初始状态为 pending
    	this.status = PENDING;
    }
    

    立即执行的函数

    Promise 接收一个立即执行的函数(执行器:excutor),该函数接收两个回调函数,resolve(成功回调)与 reject(失败回调)。

    • resolve 成功回调,将状态改为 fulfilled,并赋予成功的值
    • reject 失败回调,将状态改为 rejected,并赋予失败的原因
    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    
    function MyPromise(excutor){
        // 初始状态为 pending
        this.status = PENDING;
        // 成功的值
        this.value = undefined;
        // 失败的原因
        this.reason = undefined;
        // then 的回调函数集合,后面会用到
        fulfilledCallback = [];
        rejectedCallback = [];
        
        const resolve = (value) => {
            if (this.status === PENDING) {
                this.status = FULFILLED;
                this.value = value;
            }
        }
    
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
            }
        }
        
        try{
        	excutor(resolve, reject)
        }catch(err){
        	throw err;
        }
    }
    

    then 方法

    new Promise((...) => {...}).then(res => {}, err => {})
    

    then 用来处理成功或失败状态下的回调,并根据回调的值返回一个新的 Promises

    • 接收两个回调函数
      • onResolve 成功处理函数
      • onReject 失败处理函数
    • 返回一个新的 Promise
    • 当状态为 fulfilled 时,执行 onResolve,并返回一个新的 Promise,新 Promise 的结果由 onResolve 决定
    • 当状态为 rejected 时,执行 onReject,并返回一个新的 Promise,新 Promise 的结果由 onReject 决定
    • 当状态为 pending 时,将 onResolve 与 onReject 两个函数保存起来,等待状态变更后再执行对应的函数。
      • 由于状态为 pending 时,需要保存两个回调函数,所以需要新建两个数组来保存。
    MyPromise.prototype.then = function(onResolve, onReject){
    	// 如果用户没写 onResolve 或 onReject,就使用默认回调
        onResolve = typeof onResolve === 'undefined'?onResolve:value => value;
        onReject = typeof onReject === 'undefined'?onReject:reason => {throw reason}
        
    	// 返回一个新的 Promise
        return new MyPromise((resolve, reject) => {
        	// 当状态为 fulfilled
            if(this.status === FULFILLED){
            	setTimeout(() => {
                	try{
                    	// 执行 onResolve
                    	const result = onResolve(this.value);
                        // onResolve 如果返回一个 Promise,那么该 Promise 将决定 then 返回的 Promise 的结果
                        if(result instanceof MyPromise){
                        	result.then(resolve, reject)
                        }else{
                        	resolve(result)
                        }
                    }catch(error){
                    	reject(error)
                    }
                })
            }
            
            // 当状态为 rejected 时执行,与上面差不多
            if(this.status === REJECTED){
            	try{
                	// 与上面的唯一区别就是执行的函数与传值不一样
                    const result = onReject(this.reason);
                    if(result instanceof MyPromise){
                        result.then(resolve, reject)
                    }else{
                        resolve(result)
                    }
                }catch(error){
                    reject(error)
                }
            }
        })
    }
    

    优化一下上面的方法,顺便实现 pending 状态下的方法。

    MyPromise.prototype.then = function(onResolve, onReject){
    	return new MyPromise((resolve, reject) => {
        	// 将公用重复部分提取成一个方法
        	function handleFunc(func, value){
            	try {
                    const result = func(value);
                    // 如果返回一个 Promise
                    if (result instanceof MyPromise) {
                        result.then(resolve, reject);
                    } else {
                        resolve(result)
                    }
                } catch (err) {
                    reject(err)
                }
            }
            
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    handle(onResolve, this.value)
                })
            }
    
            if (this.status === REJECTED) {
                setTimeout(() => {
                    handle(onReject, this.reason)
                })
            }
    
    		// 状态为 pending,将回调函数保存到前面定义的函数集合中
            if (this.status === PENDING) {
            	// 保存到 fulfilledCallback
                this.fulfilledCallback.push(value => {
                    handle(onResolve, value)
                })
                // 保存到 rejectedCallback
                this.rejectedCallback.push(reason => {
                    handle(onReject, reason)
                })
            }
        })
    }
    

    当状态由 pending 状态变更到其他状态后,then 的回调函数还不会被执行,需要修改执行器 excutor 的两个回调函数,resolve、reject

    function MyPromise(excutor){
    	// 省略一部分代码
        const resolve = (value) => {
            if (this.status === PENDING) {
                this.status = FULFILLED;
                this.value = value;
                setTimeout(() => {
                	// 状态变更后执行 then 的回调函数
                    this.fulfilledCallback.forEach(fn => fn(value))
                })
            }
        }
    
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
                setTimeout(() => {
                    this.rejectedCallback.forEach(fn => fn(reason))
                })
            }
        }
    
        try {
            excutor(resolve, reject);
        } catch (err) {
            throw err;
        }
    }
    

    reject 方法

    MyPromise.reject(reason)
    

    返回一个给定原因的失败的Promise

    MyPromise.reject = function(reason){
        return new MyPromise((resolve, reject) => {
        	reject(reason)
        })
    }
    

    resolve 方法

    MyPromise.resolve(value);
    

    返回一个解析过 的 Promise,如果值为另一个 Promise,那么将直接返回这个 Promise。

    • 返回一个新的 Promise,注意:该 promise 的状态有可能是成功或失败。
      • 如果是普通值,那么将解析为成功状态并返回该值
      • 如果值是一个 Promise,那么状态将由这个 Promise 决定
    MyPromise.resolve = function(value){
    	return new MyPromise((resolve, reject) => {
        	// 如果 value 是一个 Promise,那么结果将由这个 Promise 决定
        	if(value instanceof MyPromise){
            	value.then(resolve, reject)
            }else{
            	resolve(value)
            }
        })
    }
    

    all 方法

    MyPromise.all([promise1, promise2]).then(([p1, p2]) => {}, reason => {})
    

    等待所有 promise 都成功或有一个失败后,返回一个所有 promise 的成功结果的数组或返回一个失败的原因。

    • 接收一个数组,数组的元素可以是一个 promise,也可以是一个普通值
    • 返回一个新的 promise
    • 只要有一个失败,promise.all 就会完全失败。并返回失败状态的 promise
    • 成功状态下,存入多少个 Promise 就返回多少个成功的结果,并且结果的位置与传入 Promise 的位置相同
    MyPromise.all = function (promises) {
        let results = new Array(promises.length);
        let fulfilledCount = 0;
        return new MyPromise((resolve, reject) => {
            // 如果传入的promise数组为空数组,返回一个带空数组结果的成功的 promise
            if (promises.length === 0) {
                resolve([])
            }
    
            // 处理成功的返回
            function fulfilledHandle(value, index) {
                fulfilledCount++;
                results[index] = value;
                if (fulfilledCount === promises.length) {
                    resolve(results)
                }
            }
            promises.forEach((promise, index) => {
                // 如果数组中的元素是一个 promise
                if (promise instanceof MyPromise) {
                    promise.then(res => {
                        fulfilledHandle(res, index)
                    }, reason => {
                        reject(reason)
                    })
    
                    // 不是 promise,直接添加到成功的结果集
                } else {
                    fulfilledHandle(res, index)
                }
            })
        })
    }
    

    race 方法

    MyPromise.race([promise.resolve(1), promise.reject(2)]).then(res=>{},reason=>{})
    

    该方法返回一个 promise,接收一个数组,一旦数组中的某个 promise 成功或失败,返回的promise就会更具这个状态决定成功或失败。

    注意: 只会取第一个成功或失败的 promise 或值,其他的忽略。

    MyPromise.race = function (promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach(promise => {
                if (promise instanceof MyPromise) {
                    promise.then(resolve, reject)
                } else {
                    resolve(promise)
                }
            })
        })
    }
    

    起源地下载网 » 手动实现Promise

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元