手写promise dizhi
Promise.resolve()
Promise.resolve(value)可以将任何值转成值为value,状态是fulfilled的Promise,但如果传入的值本身是Promise则会原样返回
Promise.resolve = function(value){
// 如果是Promise则直接输出它
if(value instanceof Promise){
return value;
}
return new Promise(resolve=>resolve(value));
}
Promise.reject()
和Promise.resolve类似,Promise.reject会实例化一个rejected状态的Promise。但与Promise.resolve不同的是,如果给Promise.reject传递一个Promise对象,则这个对象会成为新Promise的值
Promise.reject = function(reason){
return new Promise(resolve,reject)=>reject(reason));
}
Promise.all()
Promise.all的规则:
- 传入的所有Promise都是fulfilled,则返回由他们的值组成的,状态为fulfilled的新Promise;
- 只要有一个Promise是rejected,则返回rejected状态的新Promise,且它的值是第一个rejected的Promise的值;
- 只要有一个Promise是pending,则返回一个pending状态的新Promise;
Promise.all = function(promiseArr){
let index =0,result = [];
return new Promise((resolve,reject)=>{
promiseArr.forEach((p,i)=>{
Promise.resolve(p).then(value=>{
index++;
result[i] = value;
if(index === promiseArr){
resolve(result);
}
},err=>{
reject(err);
})
})
})
}
Promise.race()
Promise.race会返回一个由所有可迭代实例中第一个fulfilled或rejected的实例包装后的新实例。
Promise.race = function(promiseArr){
return new Promise((resolve,reject)=>{
promiseArr.forEach((p)=>{
Promise.resolve(p).then((val)=>{
resolve(val)
},err=>{
reject(err)
})
})
})
}
Promise.allSettled()
Promise.allSettled的规则:
- 所有Promise的状态都变化了,那么新返回一个状态是fulfilled的Promise,且它的值是一个数组,数组的每项由所有Promise的值和状态组成的对象;
- 如果有一个是pending的Promise,则返回一个状态是pending的新实例;
Promise.allSettled = function(promiseArr){
const result = []
return new Promise((resolve,reject)=>{
promiseArr.forEach((p)=>{
Promise.resolve(p).then((val)=>{
result.push({
value:val,
status:"fulfilled"
})
if(result.length === promiseArr.length){
resolve(result)
}
},err=>{
result.push({
reason:err,
status:"rejected"
})
if(result.length === promiseArr.length){
resolve(result)
}
})
})
})
}
Promise.any()
Promise.any的规则:
- 空数组或者所有Promise都是rejected,则返回状态是rejected的新Promise,且值为AggregateError的错误;
- 只要有一个是fulfilled状态的,则返回第一个是fulfilled的新实例
- 其他情况都会返回一个pending的新实例
Promise.any = function (promiseArr){
let index =0;
return new Promise((resolve,reject)=>{
promiseArr.forEach(p=>{
Promise.resolve(p).then(val=>{
resolve(val)
})
},err=>{
index++;
if(index === promiseArr.lenght){
reject(new AggregateError("All Promises were rejected"))
}
})
})
}
实现sleep函数
const sleep = timeout => {
return new Promise((resolve,reject) => {
setTimeout(resolve,timeout)
})
}
Generator
- Generator是一种更现代的异步解决方案,在JS语言层面支持了协程
- Generator的返回值是一个迭代器
- 这个迭代器需要手动调next才能一条一条执行yield
- next的返回值是{value,done},value是yield后面的表达式的值
- yield语句本身并没有返回值,下次调next的参数会作为上一个yield语句的返回值
- Generator自己不能自动执行,要自动执行需要引入其他方案,co模块是一个很受欢迎的自动执行方案
- thunk和co自动执行的方案思路有点类似,都是写一个局部的方法,这个方法会调用gen.next,同时这个方法本身又会传到回调函数或者promise的成功分支里面,异步结束后又继续调用这个局部方法,这个局部方法有调用gen.next,这样一致迭代,直到迭代器执行完毕
- async/await其实是Generator和自动执行器的语法糖,写法和实现原理都类似co模块的promise模式。
function co(g){
const it = g();
const exec = (res)=>{
if(res.done){
return res.value
}
return res.value.then(val=> exec(it.next(val))).catch(err=>exec(it.throw(err)))
};
exec(it.next())
}
Promise重试次数
function retry(getDate,time,interval){
return new Promise((resolve,reject)=>{
function exec(){
getDate().then(resolve).catch(err=>{
if(time ===0){
reject(err)
}else{
time--;
setTimeout(exec,interval)
}
})
}
exec()
})
}
Promise 手写
class MyPromise{
constructor(excutor){
this.state = 'pending';
this.fulfilledEvent = [];
this.rejectedEvent = [];
let resolve = (result)=>{
if(this.state !== 'pending') return;
this.state = 'fulfilled';
clearTimeout(this.timer);
this.timer = setTimeout(()=>{
this.fulfilledEvent.forEach(item=>{
if(typeof item ==='function'){
item(result)
}
})
},0)
}
let reject = (result)=>{
if(this.state !=='pending') return;
this.state='rejected';
clearTimeout(this.timer);
this.timer = setTimeout(()=>{
this.rejectedEvent.forEach(item=>{
if(typeof item === 'function'){
item(result);
}
})
},0)
}
try{
excutor(resolve,reject)
}catch(err){
reject(err)
}
}
then(resolveFn,rejectFn){
return new MyPromise((resolve,reject)=>{
this.fulfilledEvent.push(()=>{
let x= resolveFn();
x instanceof MyPromise ? x.then(resolve,reject): resolve()
})
this.rejectedEvent.push(rejectFn);
})
}
}
Promise 串行
let arrA = [
()=>{
return new Promise(resolve=>{
setTimeout(()=>{
console.log(1);
resolve(1)
},1000)
})
},
()=>{
return new Promise(resolve=>{
setTimeout(()=>{
console.log(2);
resolve(2)
},2000)
})
},
()=>{
return new Promise(resolve=>{
setTimeout(()=>{
console.log(3);
resolve(3)
},3000)
})
}
];
function execFun(arr){
return new Promise(resolve=>{
const result = [];
arr.reduce((pre,cur)=>{
return pre.then(cur).then((data)=>{
result.push(data)
})
},Promise.resolve()).then(()=>{
resolve(result);
})
})
};
let sings = [].concat(arrA,arrA,arrA);
execFun(sings);