Promise我想如今你们都很是熟悉了,主要做用就是解决异步回调问题,这里简单介绍下。javascript
Promise规范是CommonJS规范之一,而Promise规范又分了好多种,好比 Promises/A、Promises/B、Promises/Kiss等等html
有兴趣的能够到这多了解一些 http://wiki.commonjs.org/wiki/Promiseshtml5
如今比较流行的是Promise/A规范,人们对它的完善和扩展,逐渐造成了Promise/A+规范,A+已脱颖而出。java
说到这里规范是什么,能够去这里了解下git
http://promises-aplus.github.io/promises-spec/es6
http://hussion.me/2013/10/19/promises-a/github
如今已有浏览器内置支持Promise,它的api语法能够在这里查看api
http://www.html5rocks.com/zh/tutorials/es6/promises/#toc-api数组
能够看到它的api并很少,其实规范也很少,我觉的大体抓住几个重要的点就够了,promise
一、promise有三种状态,等待(pending)、已完成(fulfilled)、已拒绝(rejected)
二、promise的状态只能从“等待”转到“完成”或者“拒绝”,不能逆向转换,同时“完成”和“拒绝”也不能相互转换
三、promise必须有一个then方法,并且要返回一个promise,供then的链式调用,也就是可thenable的
四、then接受俩个回调(成功与拒绝),在相应的状态转变时触发,回调可返回promise,等待此promise被resolved后,继续触发then链
知道这几个重要的特色,咱们就能够参考浏览器内置的api来实现了,
咱们能够没必要太受规范约束,先按照本身的想法来就行了。
promise的使用大体以下
var promise = new Promise(function(resolve, reject) { setTimeout(function(){ resolve('val') }); }); promise.then(onFulfilled,onRejected).then(onFulfilled,onRejected)
主要思路就是咱们能够直接对返回的promise对象进行操做,好比then,传入回调,
这里的函数并不会当即执行,而是加入队列,等待将来的某个时间resolve时被触发执行。
有了以上说明,就能够来实现了
首先定义三个状态
var PENDING = undefined, FULFILLED = 1, REJECTED = 2;
而后实现Promise构造函数,此函数接受一个函数参数,函数参数接受俩个咱们提供的方法resolve与reject,
供使用者在将来的某个时间里调用触发执行咱们的队列,这里还要初始下当前的状态,传递的值,
以及then时保存到的队列。
大概像下面这样
var Promise = function(resolver){ if (!isFunction(resolver)) throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); if(!(this instanceof Promise)) return new Promise(resolver); var promise = this; promise._value; promise._reason; promise._status = PENDING; promise._resolves = []; promise._rejects = []; var resolve = function(value){ //状态转换为FULFILLED //执行then时保存到_resolves里的回调, //若是回调有返回值,更新当前_value } var reject = function(reason){ //状态转换为REJECTED //执行then时保存到_rejects里的回调, //若是回调有返回值,更新当前_rejects } resolver(resolve,reject); }
有了这个,咱们在实现一个then就ok了,
then里要作的就是返回一个promise供then的链式调用,
并且promise.then(onFulfilled,onRejected)时,咱们要判断当前promise的状态,
若是是pending则把onFulfilled与onRejected添加到_resolves与_rejects数组里,
不然的话根据状态,直接触发回调,这里要注意的是,若是返回的是promise,咱们要等到此promise被resolves时,
触发then链的下一个promise执行。
代码大概是这样
Promise.prototype.then = function(onFulfilled,onRejected){ var promise = this; // 每次返回一个promise,保证是可thenable的 return Promise(function(resolve,reject){ function callback(value){ var ret = isFunction(onFulfilled) && onFulfilled(value) || value; if(isThenable(ret)){ // 根据返回的promise执行的结果,触发下一个promise相应的状态 ret.then(function(value){ resolve(value); },function(reason){ reject(reason); }); }else{ resolve(ret); } } function errback(reason){ reason = isFunction(onRejected) && onRejected(reason) || reason; reject(reason); } if(promise._status === PENDING){ promise._resolves.push(callback); promise._rejects.push(errback); }else if(promise._status === FULFILLED){ // 状态改变后的then操做,马上执行 callback(promise._value); }else if(promise._status === REJECTED){ errback(promise._reason); } }); }
这里说明下
var isThenable = function(obj){
return obj && typeof obj['then'] == 'function';
}
也就是说返回的对象带有then方法,咱们就看成promise对象
到这里咱们主要的工做就完成了,其余的all,race等方法都很简单,具体能够到这里看完整的实现
https://github.com/ygm125/promise/blob/master/promise.js
下面咱们来作几个例子来看下效果
var getData100 = function(){ return Promise(function(resolve,reject){ setTimeout(function(){ resolve('100ms'); },100); }); } var getData200 = function(){ return Promise(function(resolve,reject){ setTimeout(function(){ resolve('200ms'); },200); }); } getData100().then(function(data){ console.log(data); // 100ms return getData200(); }).then(function(data){ console.log(data); // 200ms return data + data; }).then(function(data){ console.log(data) // 200ms200ms });
固然能够直接getData100().then(getData200).then(function(val){})
then能够只传一个,接受成功的回调,也能够用catch方法,接受失败的回调,
catch是then的一个语法糖,至关于promise.then(undefined, onRejected)
也能够用all来并行执行
Promise.all([getData100(),getData200()]).then(function(value){ console.log(value) // ['100ms','200ms'] });
结果的顺序与传入的顺序相同。
咱们也能够直接建立一个以obj为值的成功状态的promise,
Promise.resolve('FULFILLED').then(function(val){ console.log(val) // FULFILLED });
实现都至关简单,看代码就懂。
这里也能够作一些好玩的,好比建立一个delay方法
Promise.prototype.delay = function(ms){ return this.then(function(val){ return Promise.delay(ms,val); }) } Promise.delay = function(ms,val){ return Promise(function(resolve,reject){ setTimeout(function(){ resolve(val); },ms); }) }
咱们能够每隔多少毫秒执行一些操做
Promise.delay(1000).then(function(){ // 一些操做 }).delay(1000).then(function(){ // 一些操做 })
咱们也能够包装一个循环,执行多少次,每次延迟多少秒执行什么操做
var len = 0, words = '你好,你是谁?'; function count(num,ms,cb){ var pro = Promise.resolve(); for (var i = 0; i < num; i++) { pro = pro.delay(ms).then(function(v){ return cb(v); }); }; } count(words.length,800,function(){ var w = words.substr(0,++len); console.log(w); })
更多的东西等你来实现~