最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【Js基础不太稳】写写promise

    正文概述 掘金(tutu不秃)   2020-12-17   751

    首先需要对Promise有哪些要点有一个掌握,具体的可以查看 Promises/A+规范中文版。

    这里我列出几个手写简略版关注的点:

    1. promise 是一个拥有 then 方法的对象或函数

       1.1. then 方法接受两个参数:promise.then(onFulfilled, onRejected)

       1.2 then 方法可以被同一个 promise 调用多次

       1.3 then 方法必须返回一个 promise 对象

    2. 一个 Promise 的当前状态必须为以下三种状态中的一种:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。并且只能有如下的变化关系,不可逆转:pending -> rejected | fulfilled

    大致框架:

    const Status = {
      Pending: "pending",
      Fulfilled: "fulfiied",
      Rejected: "rejected"
    }
    
    class MyPromise {
      constructor(executor) {
        this.status = Status.Pending;
        this.value = null;
        this.reason = null;
        // 成功的callback队列
        this.fulfilledCb = [];
        // 失败的callback队列
        this.rejectedCb = [];
    
        exec(this._resolve.bind(this), this._reject.bind(this));
    
      }
    
      _resolve(value) {
        if (this.status === Status.Pending) {
          this.value = value;
          this.status = Status.Fulfilled;
          // TODO: 依次执行fulfilledCb
        }
      }
    
      _reject(reason) {
        if (this.status === Status.Pending) {
          this.reason = reason;
          this.status = Status.Rejected;
          // TODO: rejectedCb
        }
      }
    
      then(onFulfilled, onRejected) {
    
      }
    }
    

    链式调用

    Promise的链式调用,就是可以一直.then().then()的调用,这是通过then方法返回一个新的promise实例来完成的,但是具体怎么和上一个promise连通的呢?我看了很多讲解,但是自己的脑回路是一团麻,理解起来还是有困难。把我的思路整理一下,大概是这样:

    【Js基础不太稳】写写promise

    最后代码:

    const Status = {
      Pending: "pending",
      Fulfilled: "fulfiied",
      Rejected: "rejected"
    };
    
    class MyPromise {
      constructor(exec) {
        this.status = Status.Pending;
        this.value = null;
        this.reason = null;
        this.fulfilledCb = [];
        this.rejectedCb = [];
    
        try {
          exec(this._resolve.bind(this), this._reject.bind(this));
        } catch (e) {
          this._reject(e);
        }
      }
    
      _runFulfilled() {
        while (this.fulfilledCb.length) {
          const cb = this.fulfilledCb.shift();
          try {
            var returnValue = cb.handler(this.value);
          } catch (e) {
            cb.nextPromise._reject(e);
          }
    
          if (returnValue instanceof MyPromise) {
            returnValue
              .then((v) => cb.nextPromise._resolve(v))
              .catch((v) => cb.nextPromise._reject(v));
          } else {
            cb.nextPromise._resolve(returnValue);
          }
        }
      }
    
      _runRejected() {
        while (this.rejectedCb.length) {
          const cb = this.rejectedCb.shift();
          try {
            var returnValue = cb.handler(this.reason);
          } catch (e) {
            cb.nextPromise._reject(e);
          }
    
          if (returnValue instanceof MyPromise) {
            returnValue
              .then((v) => cb.nextPromise._resolve(v))
              .catch((v) => cb.nextPromise._reject(v));
          } else {
            cb.nextPromise._resolve(returnValue);
          }
        }
      }
    
      _resolve(value) {
        if (this.status === Status.Pending) {
          this.value = value;
          this.status = Status.Fulfilled;
          this._runFulfilled();
        }
      }
    
      _reject(reason) {
        if (this.status === Status.Pending) {
          this.reason = reason;
          this.status = Status.Rejected;
          this._runRejected();
    
          while (this.fulfilledCb.length) {
            const cb = this.fulfilledCb.shift();
            cb.nextPromise._reject(reason);
          }
        }
      }
    
      then(onFulfilled, onRejected) {
        const p = new MyPromise(() => {});
    
        this.fulfilledCb.push({
          handler: onFulfilled,
          nextPromise: p
        });
        if (typeof onRejected === "function") {
          this.rejectedCb.push({
            handler: onRejected,
            nextPromise: p
          });
        }
    
        if (this.status === Status.Rejected) {
          p._reject(this.reason);
        }
    
        if (this.status === Status.Fulfilled) {
          this._runFulfilled();
        }
        return p;
      }
    
      catch(onRejected) {
        const p = new MyPromise(() => {});
    
        this.rejectedCb.push({
          handler: onRejected,
          nextPromise: p
        });
    
        if (this.status === Status.Rejected) {
          this._runRejected();
        }
    
        return p;
      }
    }
    
    module.exports = MyPromise;
    

    codesandbox

    Promise.all

    Promise.myAll = (promiseArr) => {
      const arr = Array.from(promiseArr)
      const result = Array(arr.length)
      const len = arr.length
      let resolved = 0
      
      return new Promise((resolve, reject) => {
        arr.forEach((p, index) => {
          Promise.resolve(p).then((res) => {
            result[index] = res
            if (++resolved === len) {
              resolve(result)
            }
          }).catch(reject)
        })
      })
    }
    

    Promise.race

    Promise.myRace = function (iterators) {
        const promises = Array.from(iterators);
    
        return new Promise((resolve, reject) => {
            promises.forEach((promise, index) => {
                Promise.resolve(promise).then(resolve).catch(reject);
            });
        });
    };
    

    Pomisify

    const promisify = (fn, content) => {
    	return (...args) => {
    		return new Promise((resolve, reject) => {
    			const res = fn.apply(context, [...args, (err, data) => {
    				return err ? reject(err) : resolve(data)
    			}])
    		})
    	}
    }
    

    下载网 » 【Js基础不太稳】写写promise

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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