JS手写代码系列(二)Promise

89 阅读2分钟

Promise实现

	const PENDING = 'PENDING'
	const FULFILLED = 'FULFILLED'
	const REJECTED = 'REJECTED'
	//定义三种状态
	class Promise{
		constructor(exector){
			this.status = PENDING;   //初始为PENDING状态
			this.value = undefined;		//value传给resolve
			this.reason = undefined;	//reason传给reject

			this.onFulfilledCallbacks = [];   //异步回调,在PENDING时执行then无法执行,先将任务添加1到回调队列
			this.onRejectedCallbacks = [];

			const resolve = value=>{
				if(this.status === PENDING){   //状态改变后就无法回退
					this.status = FULFILLED;
					this.value = value;

					this.onFulfilledCallbacks.forEach(fn=>fn(this.value)); //状态变为FULFILLED后执行then以前添加的回调队列任务
				}
			}
			const reject = reason => {
				if(this.status === PENDING){
					this.status = REJECTED;
					this.reason = reason;

					this.onRejectedCallbacks.forEach(fn=>fn(this.reason));
				}
			}
			try{
				exector(resolve,reject);	//立即执行exector,用户可以在一定时期执行resolve和reject,使用try catch捕获到执行错误,reject抛出
			}
			catch(e){
				reject(e);
			}
			
		}
		then(onFulfilled,onRejected){     //接受俩个回调任务作为参数
			onFulfilled = typeof onFulfilled === 'function'?onFulfilled:value=>value;
			onRejected = typeof onRejected === 'function'?onRejected:
			reason => {throw new Error(reason instanceof Error?reason.message:reason)}					//解决传入then的不是函数的问题
			const self = this;
			return new Promise((resolve,reject)=>{	//实现链式调用,返回promise
				if(self.status === PENDING){
					self.onFulfilledCallbacks.push(()=>{  //resolve没有改变状态时,先将任务添加到回调队列,setTimeout模拟微任务,但不是真正的实现
						try{
							setTimeout(()=>{
								const result = onFulfilled(self.value);
								result instanceof Promise?result.then(resolve,reject):resolve(result)			//解决返回值不是Promise的问题
							})
						}
						catch(e){
							reject(e);
						}
					})
					self.onRejectedCallbacks.push(()=>{
						try{
							setTimeout(()=>{
								const result = onRejected(self.reason);
								result instanceof Promise?result.then(resolve,reject):reject(result)
							})
						}
						catch(e){
							reject(e);
						}
					})
				}
				else if(self.status === FULFILLED){  //状态为FULFILLED则直接执行回调函数
					setTimeout(()=>{
						try{
							const result = onFulfilled(self.value);
							result instanceof Promise?result.then(resolve,reject):resolve(result)
						}
						catch(e){
							reject(e)
						}
					})
				}
				else if(self.status === REJECTED){
					setTimeout(()=>{
						try{
							const result = onRejected(self.reason);
							result instanceof Promise?result.then(resolve,reject):reject(result)
						}
						catch(e){
							reject(e)
						}
					})
				}
			})
		}
		catch(onRejected){   //catch的实现,只有reject回调任务
			return this.then(null,onRejected)
		}
		
		static resolve(value){  //resolve实现,只需要判断参数是否为promise
			if(value instanceof Promise){
				return value
			}
			else{
				return new Promise((resolve,reject) => resolve(value)) //参数不是promise则返回一个新的promise
			}
		}
		
		static reject(reason){     //Promise.reject()实现
			return new Promise((resolve,reject) => {
				reject(reason)
			})
		}
	}
		static all(PromiseAll){		//Promise.all()实现
			let length = PromiseAll.length;
			let result = new Array(length);  //将每个promiseresolve的结果放在数组
			let count =0;
			return new Promise((resolve,reject)=>{
				for(let i=0;i<length;i++){
					Promise.resolve(PromiseAll[i]).then(val=>{ //resolve一下防止传入的不是promise
						result[i] = val;     //形成promise返回结果的数组
						count++;
						if(count === length){	//全部执行完则进行整体的resolve
							resolve(result);	//resolve一个promise执行形成的数组
						}
					},
						err => reject(err)		//只要一个有错误,就进行reject,改变状态
					)
				}
			})
		}
		
		static race(PromiseArr){
			return new Promise((resolve,reject)=>{
				PromiseArr.forEach((p)=>{
					Promise.resolve(p).then(  //resolve参数,防止传入的不是promise
						val => resolve(val),	//race执行率先状态改变的那一个promise
						err => reject(err)
					)
				})
			})
		}

Promise调度器

class Scheduler{
	constructor(){
		this.queue = [];		//任务队列
		this.maxCount = 2;		//最大运行数量
		this.runCount = 0;		//正在运行数量
	}
	add(promiseTask){
		this.queue.push(promiseTask);
	}
	taskStart(){
		for(let i= 0;i<this.maxCount;i++){	
			this.request();
		}
	}
	request(){
		if(!this.queue||this.queue.length||this.runCount>=this.maxCount){
			return;			//如果队列为空或者已达上限则返回
		}
		this.runCount++;	//执行一个任务,runCount++
		this.queue.shift()().then(()=>{ //执行完其中一个任务,runCount--,再请求下一个任务
			this.runCounts--;
			this.request();
		})
	}
}
const scheduler = new Scheduler();
const sleep = time => new Promise(resolve => {  //使用Promise实现sleep
	setTimeout(resolve,time)
	})
const addTask = (time,order)=>{				//一定时间后输出order值
	scheduler.add(()=>sleep(time).then(()=>console.log(order)));
}
addTask(1000,'1')
addTask(500,'2')
addTask(300,'3')
addTask(400,'4')
scheduler.taskStart();
2 3 1 4