Promise初次尝试
注意:判断一个变量是不是Promise,有三项主要的特征可作为参考。
- 该变量有三种状态
pending
、fulfilled
、rejected
- 该变量 含有
then
方法 - 该变量含有
Promise Resolution Procedure
(promise的状态转换处理方法)。
1.promise基本使用
let p = new Promise((resolve,reject)=>{
let x = Math.random();
console.log(x);
if (x > .5) {
resolve('666');
} else {
reject('GG思密达');
}
});
p.then((value)=>{ //绑定成功时的回调函数
console.log('fulfilled:',value);
},(reason)=>{ //绑定失败时的回调函数
console.log('rejected:',reason);
});
当Promise处于pending状态时,它可能转换为fulfilled或则rejected状态。
当Promise处于fulfilled状态时,它不再能转换为其它状态 且 它必须有一个值,这个值不能被更改。
当promise处于rejected时,它不再能转换为其它状态 且 它必须有一个理由,这个理由不能被更改。
2.promise的基本实现
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise(executor){
let self = this; //缓存下
self.value = undefined; //用来存放value和reason,因为promise只会处于一种状态故可只用一个变量来表示。
self.status = PENDING; //将初始状态设置为pending
self.onFulfilledCallbacks = []; //用来存放所有成功的回调函数
self.onRejectedCallbacks = []; //用来存放所有失败的回调函数
try{
executor(resolve,reject); //调用执行函数,将resolve和reject方法作为参数传入
}catch (e){
reject(e); //若执行函数中存在异常直接用抛出的值来拒绝promise
}
//-----------------------------------------------------------------------------------------------------------
function resolve(value){ //此方法会随着executor传入而传入
setTimeout(function(){
if(self.status === PENDING){ //确保状态只会改变一次
self.status = FULFILLED; //改变状态
self.value = value; //赋予一个值
self.onFulfilledCallbacks.forEach(cb => cb(self.value)); //2.2.2. //2.2.6.
}
})
}
function reject(reason){
setTimeout(function(){
if(self.status === PENDING){
self.status = REJECTED;
self.value = reason;
self.onRejectedCallbacks.forEach(cb => cb(self.value));
}
})
}
}
/*我们可以发现最终转换状态时通过Promise内部的两个方法resolve和reject,这个两个方法是在什么时候传入的呢?一个函数的参数查找,是从调用这个函数时所处的作用域开始查找的。new Promise传入的executor,是参数也是对executor函数的定义,此时executor的resolve和reject为形参。我们new Promise的时候,会执行构造函数Promise内的代码,也就是在这时executor被执行,而executor此时所处的作用域是在Promise构造函数内部,resolve和reject方法作为实参被传入。*/
2.1. then方法
- 一个promise必须提供一个then方法来使用它将要或则说已经被赋予的 value 或则 reason,一个promise的then方法接收两个参数,then中的参数皆为可选参数,如果onFulfilled或则说onRejected不是一个函数,那么将会被忽略。
- 如果onFulfilled是一个函数,它必须在promise状态转换为fulfilled时候就被调用,并且promise被赋予的value会成为这个函数(onFulfilled)的第一个参数。onFulfilled不能在promise状态转化为fulfilled前就调用onFulfilled函数不能重复调用
- 如果onRejected是一个函数,它必须在promise状态转换为rejected时候就被调用,并且promise被赋予的reason会成为这个函数(onRejected)的第一个参数。
onRejected不能在promise状态转化为rejected前就调用
onRejected函数不能重复调用 - 当一个promise转化为fulfilled状态,所有onFulfilled callback会按照回调函数通过then添加时的顺序而执行。当一个promise转化为rejected状态,所有onRejected callback会按照回调函数通过then添加时的顺序而执行。
- 如果onFulfilled或onRejected回调函数中返回了一个值,假定为x,那么调用一个 promise解析方法。
如果onFulfilled或者onRejected抛出了一个 exception(异常) e , promise2 必须以这个e作为reason来拒绝promise,使其状态改变为rejected。
如果onFulfilled不是一个函数且 promise1 的状态为fulfilled,promise2必须以 promise1 的值来fulfilled。
如果onRejected不是一个函数且 promise1 的状态为rejected,promise2必须以 promise1 的理由来rejected。
3.promise的中度实现
function Promise(){
...
function resolve(value){
setTimeout(function(){
if(self.status === PENDING){
self.status = FULFILLED;
self.value = value;
self.onFulfilledCallbacks.forEach(cb => cb(self.value));
}
})
}
function reject(reason){
setTimeout(function(){
if(self.status === PENDING){
self.status = REJECTED;
self.value = reason;
self.onRejectedCallbacks.forEach(cb => cb(self.value));
}
})
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};
let self = this,
promise2;
if(self.status === PENDING){
return promise2 = new Promise(function(resolve,reject){
self.onFulfilledCallbacks.push((value)=>{
try{
let x = onFulfilled(value);
resolvePromise(promise2,x,resolve,reject);
}catch (e){
reject(e);
}
});
self.onRejectedCallbacks.push((reason)=>{
try{
let x= onRejected(reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e){
reject(e);
}
});
});
}
};
3.1 Promise状态解析方法(promise resolution procedure)
let x= onRejected(reason);resolvePromise(promise2,x,resolve,reject);
- Promise状态解析方法的作用是将then时返回的promise2的状态改变并赋予其vlaue/reason。
- 如果 x 是一个thenable,那么该方法将试图将以 x 的状态来改变 promise2 的状态否则就将 promise2 改成 fulfilled 状态,并且value即为 x 的值
3.1.1. 如果 promise2 和 x 是引用关系,则抛出一个 TypeError 做为理由来 reject promise2。
3.1.2. 如果 x 是一个promise ,让promise2采用它的状态。
如果 x 处于pending,promise2 必须保持pending直到 x 转换为 fulfilled或则rejected。
如果 x 是 fulfilled状态,让promise2也为fulfilled,并且让promise2的value为x的value。
如果 x 是 rejected状态,让promise2也为rejected,并且让promise2的value为x的reason。
3.1.3. 如果 x 是一个对象或则函数
Let then be x.then
如果检索 x.then 时候抛出了一个异常e,那么以这个 e来 rejecte promise2。
如果 then 是一个函数,用x作为this,resolvePromise作为第一个参数,rejectPromise作为第二个参数来 call它。
如果resolvePromise被调用,循环调用 promise状态解析方法(原本的x替换为调用resolvePromise传入的参数,假定为y)。
如果rejectPromise被调用,则reject Promise2,reason为调用rejectPromise传入的参数
如果resolvePromise 和 rejectPromise 同时被调用或则多次调用,那么第一个调用的拥有优先权,其它的会被忽略。
如果调用 then 的时候抛出了一个异常 e
如果 resolvePromise 或 rejectPromise 已经被调用,则忽略它。
否则,则用这个e来 reject promise2。
3.1.4如果then不是一个函数,则用x来fulfilledpromise2
Promise.catch的基本实现
promise.prototype.catch = function(onRejected){
this.then(null,onRejected);
}
Promise.all的基本实现
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
let result = [],
count = 0;
function done(i,data){
result[i] = data;
if(++count===promises.length){
resolve(result);
}
}
for(let i=0;i{
done(i,value);
},(reason)=>{
reject(reason);
});
}
});
}
Promise.promisify的基本实现
Promise.promisify = function(fn){
return function(...args){
return new Promise((resolve,reject)=>{
fn.apply(null,[...args,function(err,data){
err?reject(err):resolve(data);
}]);
});
}
}
Promise.promisifyAll的基本实现
Promise.promisifyAll = function(obj){
for(var attr in obj){
if(obj.hasOwnProperty(key)&&typeof obj[attr]==='function'){
obj[attr+'Async'] = Promise.promisify(obj[attr]);
}
}
}
Promise.race的基本实现
Promise.race = function(promises){
return new Promise((resolve,reject)=>{
for(let i=0;i