function myPromise(executer){
this.state='pending';
this.value=undefined;
this.reason=undefined;
let that = this;
function resolve(value){
that.state='resolved'
that.value=value;
};
function reject(reason){
that.state='rejected'
that.reason = reason;
}
try{
executer(resolve,reject)
}catch(e){
reject(e)
}
}
myPromise.prototype.then=function(onFullfilled,onRejected){
if(this.state==='pending'){
}
if(this.state==='resolved'){
onFullfilled(this.value)
}
if(this.state==='rejected'){
onRejected(this.reason)
}
}
let f= new myPromise(function(resolve,reject){
resolve('value')
}).then(res=>console.log(res))
function myPromise(executer){
this.state='pending';
this.value=undefined;
this.reason=undefined;
let that = this;
this.resolveArr=[];
this.rejectArr =[];
function resolve(value){
if(that.state==='pending'){
that.state='resolved'
that.value=value;
that.resolveArr.forEach(fn=>fn())
}
};
function reject(reason){
if(that.state==='pending'){
that.state='rejected'
that.reason = reason;
that.rejectArr.forEach(fn=>fn())
}
}
try{
executer(resolve,reject)
}catch(e){
reject(e)
}
}
myPromise.prototype.then=function(onFullfilled,onRejected){
if(this.state==='pending'){
this.resolveArr.push(()=>onFullfilled(this.value))
this.rejectArr.push(()=>onRejected(this.reason))
}
if(this.state==='resolved'){
onFullfilled(this.value)
}
if(this.state==='rejected'){
onRejected(this.reason)
}
}
let f= new myPromise(function(resolve,reject){
setTimeout(() => {
resolve('value')
}, 1000);
}).then(res=>console.log(res))
let p= new myPromise(function(resolve,reject){
resolve('ddd')
}).then((res)=>console.log(res))
if (this.state==='pending')
?这个问题好。我们都知道promise的状态是只要改变后就不会再变回来,也就是只要变成resolve就不会变成reject或者变回pending,我们在内部有个try{}catch(),如果在new一个Promise时中间写function(resolve,reject){resolve();throw new Error()}
那么它岂不是先状态变成成功,然后被trycatch捕获异常又把状态变成reject?,所以这里限定Pending后状态就不会随意改变了。then may be called multiple times on the same promise.
。也就是说类似下面这种情况就会给一个实例叠加多个function:let p = new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve(11)
}, 11000);
})
p.then('xx');
p.then('ii')
function myPromise(executer){
this.state='pending';
this.value=undefined;
this.reason=undefined;
let that = this;
this.resolveArr=[];
this.rejectArr =[];
function resolve(value){
if(that.state==='pending'){
that.state='resolved'
that.value=value;
that.resolveArr.forEach(fn=>fn())
}
};
function reject(reason){
if(that.state==='pending'){
that.state='rejected'
that.reason = reason;
that.rejectArr.forEach(fn=>fn())
}
}
try{
executer(resolve,reject)
}catch(e){
reject(e)
}
}
myPromise.prototype.then=function(onFullfilled,onRejected){
let that = this;
let promise2 =new myPromise(function(resolve,reject){
if(that.state==='pending'){
that.resolveArr.push(()=>{
try{
let x = onFullfilled(that.value)
resolve(x);
}catch(e){
reject(e)
}
})
that.rejectArr.push(()=>{
try{
let x = onRejected(that.reason)
resolve(x)
}catch(e){
reject(e)
}
})
}
if(that.state==='resolved'){
try{
let x = onFullfilled(that.value)
resolve(x);
}catch(e){
reject(e);
}
}
if(that.state==='rejected'){
try{
let x = onRejected(that.reason)
resolve(x);
}catch(e){
reject(e);
}
}
})
return promise2
}
let f= new myPromise(function(resolve,reject){
setTimeout(() => {
resolve('value')
}, 1000);
}).then(res=>console.log(res)).then(res=>console.log(res))
let p=new myPromise(function(resolve,reject){
resolve('xxx')
}).then(res=>console.log(res)).then(res=>console.log(res));
if(that.status==='pending'){
return new myPromise(function(resolve,reject){
try{
that.resolveArr.push(()=>resolve(onFullfilled(that.value)))
}
catch(e){
that.rejectArr.push(()=>reject(onRejected(e)))
}
}
)}
let f= new myPromise(function(resolve,reject){
setTimeout(() => {
resolve('value')
}, 1000);
}).then(res=>new myPromise((resolve,reject)=>{setTimeout(() => {
resolve(res)
}, 1000);})).then(res=>console.log(res))
myPromise {
state: ‘pending’,
value: undefined,
reason: undefined,
resolveArr: [],
rejectArr: [] }
let f= new Promise(function(resolve,reject){
setTimeout(() => {
resolve('value')
}, 1000);
}).then(res=>new Promise((resolve,reject)=>{setTimeout(() => {
resolve(res)
}, 1000);})).then(res=>console.log(res))
let p= new Promise(function(resolve,reject){
setTimeout(() => {
resolve('1111')
}, 1000);
}).then(res=>new Promise((resolve,reject)=>{setTimeout(() => {
resolve(new Promise((resolve,reject)=>{
setTimeout(() => {
resolve(res)
}, 1000);
}))
}, 1000);})).then(res=>console.log(res))
value
1111
let p= new myPromise(function(resolve,reject){
resolve('xx')
})
let p2=p.then(res=>p2)
p2.then(res=>console.log(res),res=>console.log(res))
let p= new Promise(function(resolve,reject){
resolve('xx')
})
let p2=p.then(res=>p2)
p2.then(res=>console.log(res),res=>console.log(res))
TypeError: Chaining cycle detected for promise #
TypeError: Chaining cycle detected for promise
。x就是为了类型判断是不是Promise或者Promise里再包着Promise。resolve和reject是为了处理满足什么条件跳resolve,什么条件跳reject。myPromise.prototype.then=function(onFullfilled,onRejected){
let that = this;
let promise2 =new myPromise(function(resolve,reject){
if(that.state==='pending'){
that.resolveArr.push(()=>{
try{
let x = onFullfilled(that.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
that.rejectArr.push(()=>{
try{
let x = onRejected(that.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
}
if(that.state==='resolved'){
try{
let x = onFullfilled(that.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
}
if(that.state==='rejected'){
try{
let x = onRejected(that.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
}
})
return promise2
}
function resolvePromise(promise2,x,resolve,reject){
resolve(x)
}
console.log(1);
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
});
new Promise((resolve, reject) => {
console.log(4)
resolve(5)
}).then((data) => {
console.log(data);
})
setTimeout(() => {
console.log(6);
})
console.log(7);
1
4
7
5
2
6
3
1
4
7
5
2
3
6
Object.observe
MutationObserver
这2方法,实在想不出如何做到的,Nodejs倒是可以用proccess.nexttick()来实现插入微队列,但nodejs上的.then明显是宏队列,用settimeout即可。myPromise.prototype.then=function(onFullfilled,onRejected){
let that = this;
let promise2 =new myPromise(function(resolve,reject){
if(that.state==='pending'){
that.resolveArr.push(()=>{
setTimeout(() => {
try{
let x = onFullfilled(that.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
});
})
that.rejectArr.push(()=>{
setTimeout(() => {
try{
let x = onRejected(that.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
});
})
}
if(that.state==='resolved'){
setTimeout(() => {
try{
let x = onFullfilled(that.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
});
}
if(that.state==='rejected'){
setTimeout(() => {
try{
let x = onRejected(that.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
});
}
})
return promise2
}
function resolvePromise(promise2,x,resolve,reject){
console.log(promise2,x,resolve,reject)
resolve(x)
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('TypeError: Chaining cycle detected for promise #' ))
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => resolve(y), r => reject(r))
} else {
resolve(x)
}
} catch (e) {
reject(e)
}
} else {
resolve(x)
}
}
let obj={};
Object.defineProperty(obj,'then',{
get(){
throw new Error('xxx')
}
})
then.call(x,y=>resolve(y),r=>reject(r))
?这种跟直接x.then(y=>resolve(y),(r)=>reject(r))
有区别吗?答案是当然有区别,因为这样不会重复取两次,还记得前面有篇文章说的调用指定次数后执行的函数吗?结合上面的例子,调用2次后throw个error不就又挂了。function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('TypeError: Chaining cycle detected for promise #' ))
}
let called;
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if(called)return;
called=true;
resolvePromise(promise2,y,resolve,reject)
}, r => {
if(called)return;
called=true;
reject(r);
})
} else {//常量
resolve(x)
}
} catch (e) {
if(called)return;
called=true;
reject(e)
}
} else {//常量
resolve(x)
}
}
let p= new myPromise(function(resolve,reject){
setTimeout(() => {
resolve('1111')
}, 1000);
}).then(res=>new myPromise((resolve,reject)=>{setTimeout(() => {
resolve(new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve(res)
}, 1000);
}))
}, 1000);})).then((res)=>console.log(res))
let p= new myPromise(function(resolve,reject){
setTimeout(() => {
resolve('1111')
}, 1000);
}).then().then((res)=>console.log(res))
myPromise.prototype.then = function (onFullfilled, onRejected) {
let that = this;
onFullfilled=typeof onFullfilled ==='function'?onFullfilled:val=>val;
onRejected=typeof onRejected ==='function'?onRejected:err=>{throw err};
let promise2 = new myPromise(function (resolve, reject) {
if (that.state === 'pending') {
that.resolveArr.push(() => {
setTimeout(() => {
try {
let x = onFullfilled(that.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
});
})
that.rejectArr.push(() => {
setTimeout(() => {
try {
let x = onRejected(that.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
});
})
}
if (that.state === 'resolved') {
setTimeout(() => {
try {
let x = onFullfilled(that.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
});
}
if (that.state === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(that.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
});
}
})
return promise2
}
let p= new myPromise(function(resolve,reject){
setTimeout(() => {
resolve(new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve('11111')
}, 1000);
}))
}, 1000);
}).then((res)=>console.log(res))
myPromise {
state: ‘pending’,
value: undefined,
reason: undefined,
resolveArr: [],
rejectArr: [] }
function myPromise(executer) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
let that = this;
this.resolveArr = [];
this.rejectArr = [];
function resolve(value) {
if(value instanceof myPromise){
return value.then(resolve,reject)
}
if (that.state === 'pending') {
that.state = 'resolved'
that.value = value;
that.resolveArr.forEach(fn => fn())
}
};
function reject(reason) {
if (that.state === 'pending') {
that.state = 'rejected'
that.reason = reason;
that.rejectArr.forEach(fn => fn())
}
}
try {
executer(resolve, reject)
} catch (e) {
reject(e)
}
}
myPromise.prototype.catch=function(errcallback){
return this.then(null,errcallback);
}
myPromise.resolve=function(value){
return new myPromise((resolve,reject)=>{
resolve(value)
})
}
myPromise.reject=function(reason){
return new myPromise((resolve,reject)=>{
reject(reason)
})
}
myPromise.all= function (promises) {
function isPromise(x){
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try{
let s= typeof x.then ==='function';
return s;
}catch(e){
return false
}
}else{
return false
}
}
return new myPromise((resolve,reject)=>{
let arr = [];
let p=0;
let proccessData=(index,data)=>{
arr[index]=data;
p++;
if(p===promises.length){
resolve(arr)
}
}
for(let i=0;i<promises.length;i++){
let current= promises[i];
if(isPromise(current)){
current.then(data=>{
proccessData(i,data)
},reject)
}else{
proccessData(i,current)
}
}
})
}
let p =function () {
return new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve(11)
}, 11000);
})
}
let f =function () {
return new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve(22)
}, 12000);
})
}
myPromise.all([1,p(),2,f(),3]).then(res=>console.log(res))
[ 1, 11, 2, 22, 3 ]
class myPromise{
constructor(executer){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
let that = this;
this.resolveArr = [];
this.rejectArr = [];
function resolve(value) {
if(value instanceof myPromise){
return value.then(resolve,reject)
}
if (that.state === 'pending') {
that.state = 'resolved'
that.value = value;
that.resolveArr.forEach(fn => fn())
}
};
function reject(reason) {
if (that.state === 'pending') {
that.state = 'rejected'
that.reason = reason;
that.rejectArr.forEach(fn => fn())
}
}
try {
executer(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFullfilled,onRejected) {
let that = this;
onFullfilled=typeof onFullfilled ==='function'?onFullfilled:val=>val;
onRejected=typeof onRejected ==='function'?onRejected:err=>{throw err};
let promise2 = new myPromise(function (resolve, reject) {
if (that.state === 'pending') {
that.resolveArr.push(() => {
setTimeout(() => {
try {
let x = onFullfilled(that.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
});
})
that.rejectArr.push(() => {
setTimeout(() => {
try {
let x = onRejected(that.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
});
})
}
if (that.state === 'resolved') {
setTimeout(() => {
try {
let x = onFullfilled(that.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
});
}
if (that.state === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(that.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
});
}
})
return promise2
}
catch(errcallback){
return this.then(null,errcallback);
}
static resolve(value){
return new myPromise((resolve,reject)=>{
resolve(value)
})
}
static reject(reason){
return new myPromise((resolve,reject)=>{
reject(reason)
})
}
}
let p = new myPromise((resolve,reject)=>{
setTimeout(() => {
reject(11)
}, 11000);
})
p.then('xx').catch((e)=>console.log(e));
myPromise.resolve('111').then((res)=>console.log(res));
promises-aplus-tests -g
promises-aplus-tests 你的文件名.js
myPromise.deferred = function () {
let dfd={}
dfd.promise = new myPromise((resolve,reject)=>{
dfd.resolve=resolve;
dfd.reject=reject;
})
return dfd
}
module.exports = myPromise;