前言
大家好,我是塔塔,面试的时候常被问到封装一个promise,这里提供了一个封装好的promise.js
一、函数封装
function Promise(executor){
this.PromiseState='pending';
this.PromiseResult=null;
this.callbacks=[];
const self=this;
function resolve(data){
if(self.PromiseState!=='pending') return;
self.PromiseState='fulfilled';
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onResolve(data);
})
})
}
function reject(data){
if(self.PromiseState!=='pending') return;
self.PromiseState='reject';
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onReject(data);
})
})
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
Promise.prototype.then=function(onResolve,onReject){
const self=this;
if(typeof onReject!=='function'){
onReject=reason=>{
throw reason
}
}
if(typeof onResolve!=='function'){
onResolve=value=>value
}
return new Promise((resolve,reject)=>{
function callback(type) {
try {
let result=type(self.PromiseResult);
if(result instanceof Promise){
result.then(v=>{
resolve(v);
},r=>{
reject(r)
})
}else{
resolve(result);
}
} catch (error) {
reject(error)
}
}
if(this.PromiseState==='fulfilled'){
setTimeout(()=>{
callback(onResolve);
})
}
if(this.PromiseState==='reject'){
setTimeout(()=>{
callback(onReject);
})
}
if(this.PromiseState==='pending'){
this.callbacks.push({
onResolve:function(){
callback(onResolve)
},
onReject:function(){
callback(onReject);
},
})
}
})
}
Promise.prototype.catch=function(onReject){
return this.then(undefined,onReject)
}
Promise.resolve=function(value){
return new Promise((resolve,reject)=>{
if(value instanceof Promise){
value.then(v=>{
resolve(v)
},r=>{
reject(r)
})
}else{
resolve(value);
}
})
}
Promise.reject=function(reason){
return new Promise((resolve,reject)=>{
reject(reason);
})
}
Promise.all=function(promises){
return new Promise((resolve,reject)=>{
let count=0;
let arr=[];
for(let i=0;i<promises.length;i++){
promises[i].then(v=>{
count++;
arr[i]=v
if(count===promises.length){
resolve(arr);
}
},r=>{
reject(r);
})
}
})
}
Promise.race=function(promises){
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(v=>{
resolve(v)
},r=>{
reject(r);
})
}
})
}
二、class封装
class Promise{
constructor(executor){
this.PromiseState='pending';
this.PromiseResult=null;
this.callbacks=[];
const self=this;
function resolve(data){
if(self.PromiseState!=='pending') return;
self.PromiseState='fulfilled';
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onResolve(data);
})
})
}
function reject(data){
if(self.PromiseState!=='pending') return;
self.PromiseState='reject';
self.PromiseResult=data;
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onReject(data);
})
})
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
then(onResolve,onReject){
const self=this;
if(typeof onReject!=='function'){
onReject=reason=>{
throw reason
}
}
if(typeof onResolve!=='function'){
onResolve=value=>value
}
return new Promise((resolve,reject)=>{
function callback(type) {
try {
let result=type(self.PromiseResult);
if(result instanceof Promise){
result.then(v=>{
resolve(v);
},r=>{
reject(r)
})
}else{
resolve(result);
}
} catch (error) {
reject(error)
}
}
if(this.PromiseState==='fulfilled'){
setTimeout(()=>{
callback(onResolve);
})
}
if(this.PromiseState==='reject'){
setTimeout(()=>{
callback(onReject);
})
}
if(this.PromiseState==='pending'){
this.callbacks.push({
onResolve:function(){
callback(onResolve)
},
onReject:function(){
callback(onReject);
},
})
}
})
}
catch(onReject){
return this.then(undefined,onReject)
}
static resolve(value){
return new Promise((resolve,reject)=>{
if(value instanceof Promise){
value.then(v=>{
resolve(v)
},r=>{
reject(r)
})
}else{
resolve(value);
}
})
}
static reject(reason){
return new Promise((resolve,reject)=>{
reject(reason);
})
}
static all(promises){
return new Promise((resolve,reject)=>{
let count=0;
let arr=[];
for(let i=0;i<promises.length;i++){
promises[i].then(v=>{
count++;
arr[i]=v
if(count===promises.length){
resolve(arr);
}
},r=>{
reject(r);
})
}
})
}
static race(promises){
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(v=>{
resolve(v)
},r=>{
reject(r);
})
}
})
}
}