前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Promise原理浅析

Promise原理浅析

作者头像
IMWeb前端团队
发布2019-12-04 12:40:42
4280
发布2019-12-04 12:40:42
举报

本文作者:IMWeb moonye 原文出处:IMWeb社区 未经同意,禁止转载

Promise介绍

项目相关demo和代码地址

介绍

Promise 对象用于延迟(deferred) 计算和异步(asynchronous ) 计算.。一个Promise对象代表着一个还未完成,但预期将来会完成的操作。 Promise 对象是一个返回值的代理,这个返回值在promise对象创建时未必已知。它允许你为异步操作的成功或失败指定处理方法。 这使得异步方法可以像同步方法那样返回值:异步方法会返回一个包含了原返回值的 promise 对象来替代原返回值。

引自MDN

它解决什么问题

一个简单的示例 执行一个动画A,执行完之后再去执行另一个动画B

    setTimeout(function(){
        //A动画
        console.log('A');
        setTimeout(function() {
            //B动画
            console.log('B');
        },300)
    },300);

这里只有两个动画,如果有更多呢,就会看到一堆函数缩进

一种写法

浏览器实现方式 可以在支持Promise的版本上运行

var p = new Promise(function(resolve, reject){
  setTimeout(function(){
    //A动画
    console.log('A');
    resolve();
  },300);
});

p.then(function(){
  setTimeout(function() {
      //B动画
      console.log('B');
  },300);
});

另一种写法(jQuery版本)

jQuery版本的实现

var deferred = $.Deferred();
setTimeout(function(){
  //A动画
  console.log('A');
  deferred.resolve();
},300);

deferred.done(function() {
  setTimeout(function() {
    //B动画
    console.log('B');
  },300)
});

好像从代码上来看,是多了几行的样子,但是能用这种串行的方式来写,感觉一定很爽吧

Promise中的概念

Promise中有几个状态:

  • pending: 初始状态, 非 fulfilled 或 rejected.
  • fulfilled: 成功的操作.
  • rejected: 失败的操作.

这里从pending状态可以切换到fulfill状态(jQuery中是resolve状态),也可以从pengding切换到reject状态,这个状态切换不可逆,且fulfilled和reject两个状态之间是不能互相切换的。

一个简单版本的实现

/**
 * simple promise 
 * @param {[type]} fun [description]
 */
function PromiseB(fun) {

    this.succArg = undefined;
    this.failArg = undefined;
    this.succCbs = [];
    this.failCbs = [];
    this._status = this.STATUS.PENDING;

    this._execFun(fun);
}

PromiseB.prototype.STATUS = {
    PENDING: 1, //挂起状态
    RESOLVE: 2, //完成状态
    REJECT: 3 //拒绝状态
};

PromiseB.prototype._isFunction = function(f) {
    return Object.prototype.toString.call(f) === '[object Function]';
};

PromiseB.prototype._exec = function(callback, arg) {
    var newcallback;

    if (this._isFunction(callback)) {
        if (callback instanceof PromiseB) {
            callback.resolve(arg);
        } else {
            newcallback = new PromiseB(callback);
            newcallback.resolve(arg);
        }
    }
};

PromiseB.prototype._execFun = function(fun) {
    var that = this;

    if (this._isFunction(fun)) {
        fun(function() {
            that.succArg = Array.prototype.slice.apply(arguments);
            that._status = that.STATUS.RESOLVE;

            that.resolve.apply(that, arguments);
        }, function() {
            that.failArg = Array.prototype.slice.apply(arguments);
            that._status = that.STATUS.REJECT;

            that.reject.apply(that, arguments);
        });
    } else {
        this.resolve(fun);
    }

};

PromiseB.prototype.resolve = function() {
    var arg = arguments,
        ret,
        callback = this.succCbs.shift();
    if (this._status === this.STATUS.RESOLVE && callback) {
        ret = callback.apply(callback, arg);
        if (!(ret instanceof PromiseB)) {
            var _ret = ret;
            ret = new PromiseB(function(resolve) {
                setTimeout(function() {
                    resolve(_ret);
                });
            });

            ret.succCbs = this.succCbs.slice();
        }
        // this._exec(callback.apply(callback, arg), arg);
    }
};

PromiseB.prototype.reject = function() {
    var arg = arguments,
        ret,
        callback = this.failCbs.shift();
    if (this._status === this.STATUS.REJECT && callback) {
        ret = callback.apply(callback, arg);
        if (!(ret instanceof PromiseB)) {
            var _ret = ret;
            ret = new PromiseB(function(resolve) {
                setTimeout(function() {
                    resolve(_ret);
                }, 200);
            });
            ret.failCbs = this.failCbs.slice();
        }
    }
};

PromiseB.prototype.then = function(s, f) {
    this.done(s);
    this.fail(f);
    return this;
};

PromiseB.prototype.done = function(fun) {
    if (this._isFunction(fun)) {
        if (this._status === this.STATUS.RESOLVE) {
            fun.apply(fun, this.succArg);
        } else {
            this.succCbs.push(fun);
        }
    }
    return this;
};

PromiseB.prototype.fail = function(fun) {
    if (this._isFunction(fun)) {
        if (this._status === this.STATUS.REJECT) {
            fun.apply(fun, this.failArg);
        } else {
            this.failCbs.push(fun);
        }
    }
    return this;
};

PromiseB.prototype.always = function(fun) {
    this.done(fun);
    this.fail(fun);
    return this;
};

总结

  • promise会让代码变得更容易维护,像写同步代码一样写异步代码
  • 了解promise的原理,写个简单的实现版本就好了
  • promise的实现方案有很多,可以看这里

相关阅读

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-11-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Promise介绍
    • 介绍
      • 它解决什么问题
        • 一种写法
          • 另一种写法(jQuery版本)
            • Promise中的概念
              • 一个简单版本的实现
                • 总结
                  • 相关阅读
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档