首页 > 其他 > 详细

手写promise

时间:2020-12-28 18:05:55      阅读:25      评论:0      收藏:0      [点我收藏+]

Promise 对象是用来处理异步操作的工具,解决开发者对异步回调的烦恼。

极简版

class Defer{
  succeed = null
  fail = null
  state = ‘pending‘ 

  constructor(fn) {
    fn(this.resolve.bind(this), this.reject.bind(this))
  }
  
  resolve(result) {
    setTimeout(() => {
      this.state = ‘fulfilled‘ 
      this.succeed(result)
    })
  }

  reject(reason) {
    setTimeout(() => {
      this.state = ‘rejected‘ 
      this.fail(reason)
    })
  }

  then(succeed, fail) {
    this.succeed = succeed
    this.fail = fail
  }
}

  

1.Promise 参数 executor

当新建一个promise需要用户传递一个executor函数,其形参包含Promise自行传递的resolve,reject两个方法,分别表示代理的值解析成功并传递值,代理的值解析失败并传失败原因。而如果executor在执行过程中出错,则promise立即被拒绝(调用reject)。

function Defer(executor){ if(!(this instanceof Defer)){ throw ‘Async is a constructor and should be called width "new" keyword‘; } if(typeof executor !== ‘function‘){ throw ‘Async params must be a function‘; } try{ executor.call(this, this.resolve.bind(this), this.reject.bind(this));//传递resolve,reject方法 }catch(e){//报错立即拒绝 this.reject(e); } } Async.prototype = { constructor : Async, resolve : function(value){ this.value = value;//缓存代理的值 }, reject : function(reason){ this.rejectReason = reason;//缓存失败原因 } }

2.promise状态

Defer.prototype = { constructor : Async, resolve : function(value){ this.value = value;//缓存代理的值 this.status = ‘resolved‘; }, reject : function(reason){ this.rejectReason = reason;//缓存失败原因 this.status = ‘rejected‘; } }

3.then(onFulfilled,onRejected)重要部分

   then返回的是新的promise对象

//then中的onfulfilled传的参数为数值,则直接返回数值,如果为函数,则直接去调用函数。

   then参数调用时期和要求

(1) onFulfilled(onResolved):可选参数,如果不是函数则必须忽略;

(2) onRejected:可选参数,如果不是函数则必须忽略;

(3) 当promise成功执行,所有onFulfilled按注册顺序执行,如果promise被拒绝,所有onRejected按注册顺序执行;

(4) onFulfilled 和 onRejected必须作为纯函数调用

(5) promise的executor执行完毕并调用resolve或reject方可调用then参数onFulfilled 和 onRejected。

(6) 无论promise状态是resolved还是rejected,只要还有未执行onFulfilled,onRejected或catch(只处理reject状态)存在且调用,返回的promise均为resolved状态;(该规则在下一节”triggerThen处理”和下下节”catch异常“会有注释,一看便知)

对于规则4,必须作为传函数调用。所以传函数调用,是不包含在Object的属性当中直接引用,并且this的值是undefined。
  onFulfilled.call(undefined, promise_value);
对于规则5,等待executor执行完毕并调用resolve或reject方可调用then参数。then方法就是缓存参数。
function Defer(executor) {
            if (!(this instanceof Defer)) {
                throw ‘Defer is a constructor and should be called width "new" keyword‘;
            }

            if (typeof executor !== ‘function‘) {
                throw ‘Defer params must be a function‘;
            }

            this.thenCache = [];//{resolve:,reject:}
            this.errorHandle = null;
            this.status = ‘pendding‘;
            this.value = null;
            this.rejectReason = null;
            var self = this;
            setTimeout(function () {
                try {
                    executor.call(self, self.resolve.bind(self), self.reject.bind(self));//传递resolve,reject方法
                } catch (e) {
                    self.reject(e);
                }
            }, 0);
            return this;
        }

        Defer.prototype.resolve = function (value) {
            this.status = ‘resolved‘;
            this.value = value;
            this.triggerThen();
        };
        Defer.prototype.reject = function (reason) {
            this.status = ‘rejected‘;
            this.rejectReason = reason;
            this.triggerThen();
        };
        Defer.prototype.then = function (resolve, reject) {
            var todo = { resolve: resolve, reject: reject };
            this.thenCache.push(todo);
            return this;
        };
        Defer.prototype.triggerThen = function () {
            var current = this.thenCache.shift();
            var res = null;

            if (!current && this.status === ‘resolved‘) {//成功解析并读取完then cache
                return this;
            } else if (!current && this.status === ‘rejected‘) {//解析失败并读取完then cache,直接调用errorHandle
                if (this.errorHandle) {
                    this.value = this.errorHandle.call(undefined, this.rejectReason);
                    this.status = ‘resolved‘;
                }
                return this;
            };

            if (this.status === ‘resolved‘) {
                res = current.resolve;
            } else if (this.status === ‘rejected‘) {
                res = current.reject;
            }

            if (typeof res === ‘function‘) {
                try {
                    this.value = res.call(undefined, this.value || this.rejectReason);//重置promise的value
                    this.status = ‘resolved‘;
                    this.triggerThen();//继续执行then链
                } catch (e) {
                    this.status = ‘rejected‘;//异常,则promise为reject
                    this.rejectReason = e;
                    return this.triggerThen();//触发then链
                }
            } else {//不是函数则忽略
                this.triggerThen();
            }
        };
        Defer.prototype.catch = function (fn) {
            if (typeof fn === ‘function‘) {
                this.errorHandle = fn;
            }
        }; 

手写promise.all

(方法返回一个promise实例,所有的promise都返回resolved,则resolved。如果有一个promise失败(rejected),则实例回调失败,失败原因返回第一个promise的结果)

Promise2.all = function(arrP) {
  let list = []
  let len = 0
  let hasErr = false
  return new Promise2((resolve, reject) => {
    for(let i = 0; i < arrP.length; i++) {
      arrP[i].then( data=> {
        list[i] = data
        len++
        len === arrP.length && resolve(list)
      }, error => {
        !hasErr && reject(error)
        hasErr = true
      })
    }
  })
}  

手写Promise.race

方法返回一个promise实例,一旦迭代器中的某个 promise 完成(resolved)或失败(rejected),返回的 promise 就会 resolve 或 reject   

返回第一个resolve或者reject的结果值。

Promise2.race = function(arrP) {
  let hasValue = false
  let hasError = false
  return new Promise2((resolve, reject) => {
    for(let i = 0; i < arrP.length; i++) {
      arrP[i].then(data => {
        !hasValue && !hasError && resolve(data) 
        hasValue = true
      }, error => {
        !hasValue && !hasError &&reject(error)
        hasError = true
      })
    }
  })
}

手写Promise.allSettled()

方法返回一个在所有给定的promise都已经fulfilledrejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

适用于:多个彼此不依赖的异步任务完成时,可以知道每个promise的结果。

Defer.allSettled = function (values) {
            function isPromise(x) {
                if ((typeof x === ‘object‘ && x != null) || typeof x === ‘function‘) {
                    if (typeof x.then == ‘function‘) {
                        return true;
                    }
                }
                return false;
            }
            return new Defer((resolve, reject) => {
                let arr = [];
                let times = 0;
                function collectResult(val, key, obj) {
                    arr[key] = obj;
                    if (++times === values.length) {
                        return resolve(arr);
                    }
                }
                // 循环每一项拿到返回结果
                values.forEach((element, index) => {
                    if (element && isPromise(element)) {
                        element.then(y => {
                            let obj = {
                                status: ‘fulfilled‘,
                                value: y,
                            }
                            collectResult(y, index, obj)
                        }, (err) => {
                            let obj = {
                                status: "rejected",
                                reason: err
                            }
                            collectResult(err, index, obj)
                        })
                    } else {
                        let obj = {
                            status: ‘fulfilled‘,
                            value: value,
                        }
                        collectResult(value, index, obj)
                    }
                });

            })
        }

手写promise.any()

返回第一个成功的 promise 。只要有一个 promise 成功此方法就会终止,它不会等待其他的 promise 全部完成。如果没有成功的,则将返回一个失败的promise和AggregateError类型的实例。是一个Error的子类,将用于把单一的错误集合在一起。

 Defer.any = function (values) {
            const num = values.length;
            const rejectedList = new Array(num);
            let rejectedNum = 0;
            return new Defer((resolve, reject) => {
                values.forEach((el, i) => {
                    Defer.resolve(el).then(
                        resolve(el)
                    ).catch(err => {
                        rejectedList[index] = err;
                        if (++rejectedNum === num) {
                            reject(rejectedList);
                        }
                    })
                })
            })
        } 

手写实现 Promise.prototype.finally()

finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。

实例执行完then或者catch触发,

Defer.prototype.finally=function(cb){
            return new Defer((resolve,reject)=>{
                this.then((result)=>{
                    cb();
                    resolve(result); 
                },(reason)=>{
                    cb();
                    reject(reason);
                })
            })
        }

代码完整:https://github.com/yaqian96/promise.git

 

手写promise

原文:https://www.cnblogs.com/lyq1996/p/14202289.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!