Promise原理
参考https://github.com/chunpu/promise/blob/master/promise.js
个人认为原博的实现有点问题 在next函数的实现上, 会导致无限的调用
看看一般Promise的用法
promise = new Promise(function(resolve, reject) {
//...
resolve(1);
//...
})
.then(function(val){}, functioin(err){})
.then(function(val){}, functioin(err){})
显然要实现的功能是这样的
Promise对象有then方法
Promise对象接受一个参数fn(resolve, reject)
Promise可以连续的then调用
function Promise(resolver) {
var queue = [];//链式调用数组
resolver(resolve, reject);
//state 0 是resolve
function next(state, val){
var arr;
if(arr = queue.shift()){
arr[state](val);
}
}
function resolve(x){
next(0, x)
}
function reject(reason){
next(1, reason);
}
//Promise最明显的特征 是可以then then接收两个参数
//then就是将传入的函数放入队列中
this.then = function(resolve, reject){
queue.push([resolve, reject]); //resovle reject 这两个参数也都是函数
}
}
var p = new Promise(function(resolve){
resolve('ok')
})
p.then(function(x){
console.log(x);
})
有个问题 那就是创建一个Promise对象的时候就调用了 resolver(resolve, reject); 也就是调用了resolve('ok') 也就是调用了next 也就是使queue函数出队列并执行
但是这个时候 queue 还没有push任何值 执行不能继续 毕竟这个是在Promise对象完成创建之后才调用then
为了使next在then中的函数全部进到队列之后再执行 用一个setTimeout把 next中的逻辑包裹
function Promise(resolver) {
var queue = [];
resolver(resolve, reject);
function next(state, val){
var arr;
//为了使resolve晚于 then 执行 暂时用一个setTimeout
setTimeout(function(){
if(arr = queue.shift()){
arr[state](val);
}
}, 0);
}
function resolve(x){
next(0, x);
}
function reject(reason){
next(1, reason);
}
this.then = function(resolve, reject){
queue.push([resolve, reject]);
}
}
var p = new Promise(function(resolve){
setTimeout(function(){
resolve('ok')
},1200);
}).then(function(data){
console.log(data);
})
不过我们知在一个then中 return 可能不仅仅是一个简单地的value , 有可能再次返回一个Promise对象 而下一个then中resolve函数的的data是这个Promise对象resolve()的值
听起来很复杂 针对return一个Promise对象的情况 就是调用这个对象的then
然后再次进入next 而next的参数就是返回的Promise对象的resolve的值
function Promise(resolver) {
var queue = []; //链式调用数组
resolver(resolve, reject);
//state 0 是resolve
function next(state, val) {
var arr;
var chainRs;
setTimeout(function() {
if (arr = queue.shift()) {
chainRs = arr[state](val);
if(!chainRs) return;
//某一个resolve函数返回的又是一个Promise对象
if (chainRs && typeof chainRs.then == 'function') {
chainRs.then(resolve, reject);
} else {
//resolve函数返回一个普通的值
resolve(chainRs) //.then(resolve, reject);
}
}
}, 0);
}
function resolve(x) {
next(0, x);
}
function reject(reason) {
next(1, reason);
}
//Promise最明显的特征 是可以then then接收两个参数
//then就是将传入的函数放入队列中
this.then = function(resolve, reject) {
queue.push([resolve, reject]); //resovle reject 这两个参数也都是函数
return this;
}
}
Promise.resolve = Promise.cast = function(x) {
return new Promise(function(resolve) {
resolve(x);
})
}
测试
var p = new Promise(function(resolve) {
setTimeout(function() {
resolve('ok')
}, 1200);
}).then(function(data) {
console.log(data);
// return 555;
return new Promise(function(resolve){
setTimeout(function(){
resolve('wahaha');
}, 2200);
})
})
.then(function(data) {
console.log('2nd then', data);
return 666;
})
.then(function(data) {
console.log('3rd then', data);
});
完善 增加Promise.all() Promise.resolve()
Promise.resolve = Promise.cast = function(x) {
return new Promise(function(resolve) {
resolve(x);
})
}
Promise.all = function(promises){
var len = promises.length;
var results = [];
return new Promise(function(resolve){
promises.forEach(function(p, i){
p.then(function(data){
results[i] = data;
len--;
if(len == 0){
resolve(results);
}
}, function(err){
console.log(err);
});
});
});
}
//=================================
Promise.resolve(999)
.then(function(data){
console.log(data);
return new Promise(function(resolve, reject){
// resolve('xixi');
reject('xixi');
})
}).then(function(data){
console.log(data);
},function(err){
console.log(err);
})
Promise.all([
new Promise(function(resolve){
setTimeout(function(){
resolve(111);
}, 1000);
}),
new Promise(function(resolve){
resolve(222);
})
]).then(function(results){
console.log(results);
})