Reference data

  • Front-end development core knowledge advanced – do you think I really want you to write Promise, in fact, are basically written after reading this article, if you want to better understand can see the big guy’s article;

The API to implement

  • Constructor method
  • Then method
  • Catch method
  • Resolve static method
  • Reject static method
  • All Static methods
  • Race static method
  • All the code

Promise to explain

  1. Promise Most of these methods will return a Promise object, because we’re going to do a chain call;
  2. There may be three states when calling then,catch, etc., namely, depressing, Rejected, and pending. The former two states are easy to understand. For pending, you need to use an array to save the callback method and empty the callback list in the array when you call resolve/ Reject.
  3. Each argument passed to the then/catch method is a callback method that returns data in the Result /error property of the returned Promise object.

Promise constructor

Example use of the Promise constructor

let p = new Promise((resolve,reject)=>{ resolve('result'); / / or reject (" error "); })Copy the code

So the Promise constructor must accept a method, and we can deduce its constructor based on its properties

Class Promise{// Reject ledarray and onRejectArray are used to handle asynchronous logic, assuming, for example, that a.then method is bound before a reject. Private onfunction ledarRay: Function[] = []; private onRejectedArray : Function[] = []; status : PROMISE_STATUS = PROMISE_STATUS.PENDING; result : any = null; error : any = null; constructor(apply: Function){ const onFulfill = (result)=>{ if(this.status === PROMISE_STATUS.PENDING){ this.status = PROMISE_STATUS.FULFIL; this.result = result; / / resolve the onFulfilledArray binding method to execute the enclosing onFulfilledArray. ForEach (fun = > {fun (result); }) } }, onReject = (error)=>{ if(this.status === PROMISE_STATUS.PENDING){ this.status = PROMISE_STATUS.REJECT; this.error = error; / / reject all the inside of the array method to perform the enclosing onRejectedArray. ForEach (fun = > {fun (error); }) } } apply(onFulfill,onReject); }}Copy the code

This part is the most simple, just need to have reverse thinking, basically can understand;

Implementation of then methods

The Primise. Then method receives two parameters, the resolve callback method and the reject callback method, and only one of them will be executed. The THEN method is the core part of the whole Promise, which is also the most difficult part to understand. The then method accepts two callbacks, resolve and reject, in three cases according to promise.status:

  1. If status === ‘Fulfiled’, call the resolve callback and return the result to generate a new Promise.
  2. If status === ‘reject’, reject (reject) returns a new Pomise;
  3. When status === ‘Pending’, we need to wait for the result of the Promise, but we need to return a Promise, so we have to push into onredarray, onRejectedArray;
// The resolvePromise method is explained later; resolvePromise(promise2 : Promise, result : any, resolve : Function, reject : Function){ } then(onFulfilled : Function, onFulfilled: Function) : Promise {// If there is no fulfilled, then add the default onFulfilled/ onFulfilled = onFulfilled? onFulfilled : data => data; onRejected = onRejected ? onRejected : error => error; let promise2 : Promise; If (this.status === promise_status.fulfil){// Return a new Promise object return promise2 = new Promise((resolve,reject)=>{ try{ let result = onFulfilled(this.result); / / here's a encapsulates the method of processing the result / / object can handle the result is a Promise, or other data this. ResolvePromise (promise2, result, resolve, reject); }catch(e){ reject(e); Promise_status. REJECT (this.status === promise_status. REJECT){return promise2 = new Promise((resolve,reject)=>{ try{ let result = onRejected(this.error); this.resolvePromise(promise2,result,resolve,reject); }catch(e){ reject(e); }})} / Promise state when/if the call is Pending, you need to put back into the onFulfilledArray/onRejectedArray array, If (this.status === promise_status.pending){return promise2 = new Promise((resolve,reject)=>{ this.onFulfilledArray.push(result=>{ try{ let _result = onFulfilled(result); this.resolvePromise(promise2, _result, resolve, reject); }catch(e){ reject(e) } }) this.onRejectedArray.push(result=>{ try{ let _result = onRejected(result); this.resolvePromise(promise2, _result, resolve, reject); }catch(e){ reject(e) } }) }) } return this; }Copy the code

ResolvePromise method

The resolvePromise method is the logic we encapsulate to handle the result or error associated with the newly generated Promise and the result returned by the callback. Result may have the following situations:

  1. Promise comes, in the result of promise. then processing;
  2. Direct treatment;
resolvePromise(promise2 : Promise, result : any, resolve : Function, reject : Function){
	if(promise2 === result){
		return reject('error');
	}
	if(result instanceof Promise){
		if(result.status === PROMISE_STATUS.PENDING){
			result.then(value=>{
				this.resolvePromise(promise2,value,resolve,reject);
			}, reject)
		}else{
			result.then(resolve,reject);
		}
		return;
	}
	resolve(result);
}

Copy the code

Promise.catch

catch(onReject: Function) : Promise { if(this.status === PROMISE_STATUS.FULFIL){ return this; } let promise2; return promise2 = new Promise((resolve,reject)=>{ if(this.status === PROMISE_STATUS.REJECT){ let result = onReject(this.error); this.resolvePromise(proimse2,result,resolve,reject); return; } this.then((result)=>{ this.resolvePromise(promise2,result,resolve,reject); },(error)=>{ this.resolvePromise(promise2,onReject(error),resolve,reject); })})}Copy the code

Promise.reject

	static reject(error){
		return new Promise((resolve,reject)=>{
			reject(error);
		});
	}
	

Copy the code

Promise.resolve

static resolve(result){
		return new Promise((resolve,reject)=>{
			resolve(result);
		});
	}
	
Copy the code

Promise.all

static all(promises: Promise[]): Promise{ let resultArray = new Array(promises.length); return new Promise((resolve,reject)=>{ let n = 0, maxLength = resultArray.length; let setResult = function(item,idx){ if(idx + 1 > maxLength) reject('cao'); if(! resultArray[idx]){ n ++; resultArray[idx] = item; if(n == maxLength ){ resolve(resultArray); } } } for(let idx =0; idx < promises.length; idx ++ ){ let item = promises[idx]; try{ if(item instanceof Promise){ item.then((result)=>{ setResult(result,idx); }, (error)=>{ reject(error); }) }else{ setResult(promises[idx],idx); } }catch(e){ reject(e); }}})}Copy the code

Promise.race

static race(promises : Promise[]) : Promise{ return new Promise((resolve,reject)=>{ let flag = false; promises.forEach(p => { if(flag){ return; } if(p instanceof Promise){ return p.then(result=>{ if(flag){ return; } flag = true; resolve(result); },error=>{ if(flag){ return; } flag = true; reject(error); }) } flag = true; resolve(p); })})}Copy the code

Full code Promise

enum PROMISE_STATUS { PENDING, FULFIL, REJECT, } class Promise{ private onFulfilledArray : Function[] = []; private onRejectedArray : Function[] = []; status : PROMISE_STATUS = PROMISE_STATUS.PENDING; result : any = null; error : any = null; constructor(apply: Function){ const onFulfill = (result)=>{ if(this.status === PROMISE_STATUS.PENDING){ this.status = PROMISE_STATUS.FULFIL; this.result = result; this.onFulfilledArray.forEach(fun=>{ fun(result); }) } }, onReject = (error)=>{ if(this.status === PROMISE_STATUS.PENDING){ this.status = PROMISE_STATUS.REJECT; this.error = error; this.onRejectedArray.forEach(fun=>{ fun(error); }) } } apply(onFulfill,onReject); } resolvePromise(promise2 : Promise, result : any, resolve : Function, reject : Function){ if(promise2 === result){ return reject('error'); } if(result instanceof Promise){ if(result.status === PROMISE_STATUS.PENDING){ result.then(value=>{ this.resolvePromise(promise2,value,resolve,reject); }, reject) }else{ result.then(resolve,reject); } return; } resolve(result); } then(onFulfilled : Function, onRejected : Function) : Promise { onFulfilled = onFulfilled ? onFulfilled : data => data; onRejected = onRejected ? onRejected : error => error; let promise2 : Promise; if(this.status === PROMISE_STATUS.FULFIL){ return promise2 = new Promise((resolve,reject)=>{ try{ let result = onFulfilled(this.result); this.resolvePromise(promise2,result,resolve,reject); }catch(e){ reject(e); } }) } if(this.status === PROMISE_STATUS.REJECT){ return promise2 = new Promise((resolve,reject)=>{ try{ let result = onRejected(this.error); this.resolvePromise(promise2,result,resolve,reject); }catch(e){ reject(e); } }) } if(this.status === PROMISE_STATUS.PENDING){ return promise2 = new Promise((resolve,reject)=>{ this.onFulfilledArray.push(result=>{ try{ let _result = onFulfilled(result); this.resolvePromise(promise2, _result, resolve, reject); }catch(e){ reject(e) } }) this.onRejectedArray.push(result=>{ try{ let _result = onRejected(result); this.resolvePromise(promise2, _result, resolve, reject); }catch(e){ reject(e) } }) }) } return this; } catch(onReject: Function) : Promise { if(this.status === PROMISE_STATUS.FULFIL){ return this; } let promise2; return promise2 = new Promise((resolve,reject)=>{ if(this.status === PROMISE_STATUS.REJECT){ let result = onReject(this.error); this.resolvePromise(proimse2,result,resolve,reject); return; } this.then((result)=>{ this.resolvePromise(promise2,result,resolve,reject); },(error)=>{ this.resolvePromise(promise2,onReject(error),resolve,reject); }) }) } static reject(error){ return new Promise((resolve,reject)=>{ reject(error); }); } static resolve(result){ return new Promise((resolve,reject)=>{ resolve(result); }); } static all(promises: Promise[]): Promise{ let resultArray = new Array(promises.length); return new Promise((resolve,reject)=>{ let n = 0, maxLength = resultArray.length; let setResult = function(item,idx){ if(idx + 1 > maxLength) reject('cao'); if(! resultArray[idx]){ n ++; resultArray[idx] = item; if(n == maxLength ){ resolve(resultArray); } } } for(let idx =0; idx < promises.length; idx ++ ){ let item = promises[idx]; try{ if(item instanceof Promise){ item.then((result)=>{ setResult(result,idx); }, (error)=>{ reject(error); }) }else{ setResult(promises[idx],idx); } }catch(e){ reject(e); } } }) } static race(promises : Promise[]) : Promise{ return new Promise((resolve,reject)=>{ let flag = false; promises.forEach(p => { if(flag){ return; } if(p instanceof Promise){ return p.then(result=>{ if(flag){ return; } flag = true; resolve(result); },error=>{ if(flag){ return; } flag = true; reject(error); }) } flag = true; resolve(p); }}})})Copy the code