资讯专栏INFORMATION COLUMN

promise原理探究

Imfan / 2309人阅读

摘要:直接修改状态为指定值,然后接着执行回调呜呜呜,有时候总会犯傻不是,上面第一种维护一个定时器,效率低下第二种把状态变得很麻烦和复杂其实很多事情之所以复杂,是因为我们想的太多。根本没那么复杂,就三个状态,搞毛线定时器,状态跟踪。

前言

Promise是个什么玩意,大家都知道,度娘告诉我,以同步方式书写异步,解决回调地狱。。。

状态机

早闻Promise的大名,简单介绍,根据状态改变来执行相应处理函数。
Promise的状态极其简单,只有 "pending", "resolved", "rejected"三种状态
然后就是如何实现的问题,最关键的当然是监听到状态的更新,然后才能做出回应,那么如何知道状态变了呢?
最初单纯的我开了一个脑洞,有以下想法:

写一个定时器不断查询状态值,如果有变化,那么执行回调

利用ES5的 Object.defineProperty(obj, prop, descriptor)来追踪状态变化。

直接修改状态为指定值,然后接着执行回调

呜呜呜,有时候总会犯傻不是,上面第一种维护一个定时器,效率低下;第二种把状态变得很麻烦和复杂;
其实很多事情之所以复杂,是因为我们想的太多。
Promise根本没那么复杂,就三个状态,搞毛线定时器,状态跟踪。
利用观察者模式,只需要通过特定书写方式注册对应状态的事件处理函数,然后更新状态,调用注册过的处理函数即可。这个特定方式就是 then ,done ,fail, always...等方法;更新状态触发时机就是resolve, reject方法。

简单实现

理论分析:

写一个类对象,维护一个 state,值有3种:"pending", "resolved", "rejected"

通过then done fail always方法注册回调处理函数

通过resolve reject分别更新对应状态,并且调用注册函数

代码如下:

/**
 * [3种状态]
 * @type {String}
 */
var PENDING = "pending";
var RESOLVED = "resolved";
var REJECTED = "rejected";

/**
 * [Promise类实现]
 * 构造函数传入一个fn,有两个参数,resolve:成功回调; reject:失败回调;
 * state: 状态存储
 * doneList: 成功处理函数列表
 * failList: 失败处理函数列表
 * done: 注册成功处理函数
 * fail: 注册失败处理函数
 * then: 同时注册成功和失败处理函数
 * always: 一个处理注册到成功和失败,都会调用
 * resolve: 更新state为:RESOLVED,并且执行成功处理队列
 * reject: 更新state为:REJECTED,并且执行失败处理队列
 */
var Promise = (function (){
    function Promise(fn){
        this.state = PENDING;
        this.doneList = [];
        this.failList = [];
        this.fn = fn;
        this.fn(this.resolve.bind(this), this.reject.bind(this))
    }

    var p = {
        done: function (cb){
            if(typeof cb == "function")
                this.doneList.push(cb)
            return this;
        },
        fail: function(cb){
            if(typeof cb == "function")
                this.failList.push(cb);
            return this;
        },
        then: function(success, fail){
            this.done(success || noop).fail(fail || noop)
            return this;
        },
        always: function(cb){
            this.done(cb).fail(cb)
            return this;
        },
        resolve: function(){
            this.state = RESOLVED;
            var lists = this.doneList;
            for(var i = 0, len = lists.length; i

使用方式,请到https://github.com/donglegend/MyPromise下载使用

源码下载

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96318.html

相关文章

  • Async:简洁优雅的异步之道

    摘要:前言在异步处理方案中,目前最为简洁优雅的便是函数以下简称函数。声明式表达式作为对象属性作为对象属性的简写式箭头函数返回值执行函数,会固定的返回一个对象。如果该对象最终成功,则会返回成功的返回值,相当将替换成返回值。 前言 在异步处理方案中,目前最为简洁优雅的便是async函数(以下简称A函数)。经过必要的分块包装后,A函数能使多个相关的异步操作如同同步操作一样聚合起来,使其相互间的关系...

    leiyi 评论0 收藏0
  • 前端错误监控与收集探究

    摘要:这样很容易造成大的损失,提前做好错误收集和处理,可以减少损失。 编写代码只是做好项目的一小部分,写代码难免会碰到错误。因此,在项目上线后,我们还需要主动对项目的错误进行收集,不能等用户发现错误,再联系我们,我们再去处理。这样很容易造成大的损失,提前做好错误收集和处理,可以减少损失。 本人并没有做过相关的工作,下面的文章只是我在学习中的一点思考和总结,可能有比较多不足和错误的地方,希望大...

    ZoomQuiet 评论0 收藏0
  • javascript知识点

    摘要:模块化是随着前端技术的发展,前端代码爆炸式增长后,工程化所采取的必然措施。目前模块化的思想分为和。特别指出,事件不等同于异步,回调也不等同于异步。将会讨论安全的类型检测惰性载入函数冻结对象定时器等话题。 Vue.js 前后端同构方案之准备篇——代码优化 目前 Vue.js 的火爆不亚于当初的 React,本人对写代码有洁癖,代码也是艺术。此篇是准备篇,工欲善其事,必先利其器。我们先在代...

    Karrdy 评论0 收藏0
  • 我们不背诵 API,只实现 API

    摘要:接下来,我们换一种思路,用一个相对较新的来实现方法。从这道题目看出,相比考察死记硬背,这样的实现更有意义。对数组的操作我们不能陌生,其中方法更要做到驾轻就熟。最后,我们再看下社区上著名的和的实现。 有不少刚入行的同学跟我说:JavaScript 很多 API 记不清楚怎么办?数组的这方法、那方法总是傻傻分不清楚,该如何是好?操作 DOM 的方式今天记,明天忘,真让人奔溃! 甚至有的开发...

    wudengzan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<