转载

Promise原理浅析

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两个状态之间是不能互相切换的。

Promise原理浅析

一个简单版本的实现

/**  * 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的实现方案有很多,可以看 这里
正文到此结束
Loading...