learn how to cook promise
标准中规定:
- Promise对象初始状态为
Pending
,在被resolve
或reject
时,状态变为Fulfilled
或Rejected
- resolve接收成功的数据,reject接收失败或错误的数据
- Promise对象必须有一个
then
方法,且只接受两个可函数参数onFulfilled
、onRejected
标准中规定:
- then 方法必须返回一个新的
Promise实例
(ES6中的标准,Promise/A+中没有明确说明) - 为了保证 then中回调的执行顺序,
onFulfilled
或onRejected
必须异步调用
Promise.all = function(iterable){
var _this = this;
return new this(function(resolve, reject){
if(!iterable || !Array.isArray(iterable)) return reject( new TypeError('must be an array') );
var len = iterable.length;
if(!len) return resolve([]);
var res = Array(len), counter = 0, called=false;
iterable.forEach(function(v, i){
(function(i){
_this.resolve(v).then(function(value){
res[i]=value;
if(++counter===len && !called){
called = true;
return resolve(res)
}
}, function(err){
if(!called){
called = true;
return reject(err);
}
})
})(i)
})
})
}
用于并行执行promise组成的数组(数组中可以不是Promise对象,
在调用过程中会使用 Promise.resolve(value)
转换成Promise对象),如果某个promise的状态率先改变,
就获得改变的结果,返回一个新的Promise对象
Promise.race = function(iterable){
var _this = this;
return new this(function(resolve, reject){
if(!iterable || !Array.isArray(iterable)) return reject( new TypeError('must be an array') );
var len = iterable.length;
if(!len) return resolve([]);
var called = false;
iterable.forEach(function(v, i){
_this.resolve(v).then(function(res){
if(!called){
called = true;
return resolve(res);
}
}, function(err){
if(!called){
called = true;
return reject(err);
}
})
})
})
}
用于包装任意对象为promise对象,返回一个新的promise,并且状态是resolved
Promise.resolve = function(value){
if(value instanceof this) return value;
return executeCallback.bind(new this())('resolve', value);
}
用于包装任意对象为promise对象,返回一个新的promise,并且状态是rejected
Promise.reject = function(value){
if(value instanceof this) return value;
return executeCallback.bind(new this())('reject', value);
}