Promise is a solution to asynchronous programming that is more reasonable and powerful than callback functions and events.
Native promises are used as follows:
Let p=new Promise(function(resolve,reject){resolve(' succeed '); / / reject (' failure '); }); p.then(function(data){ console.log(data); },function(err){ console.log(err); });Copy the code
Function Promise(executor){// Executor is an executor function let self = this; self.status = 'pending'; self.value = undefined; // Default success value self.reason = undefined; Function resolve(value){if(self.status === 'pending'){self.status = 'resolved'; self.value = value; If (self.status === 'pending'){self.status = 'rejected'; self.reason = reason; } } try{ executor(resolve,reject); }catch(e){// Reject reject(e); }}; Promise.prototype.then = function(onFulfilled,onRejected){ let self = this; if(self.status === 'resolved'){ onFulfilled(self.value); } if(self.status === 'rejected'){ onRejected(self.reason); }}; module.exports = Promise;Copy the code
Start by defining a Promise function, and accept an executor that executes resolve and reject, and defines the private properties Status, value, and Reason. A Promise has three states. Status records them: Initial status is Pending and Resolved and Rejected
Then use prototype to mount a then method that passes in a successful callback and a failed callback
Finally, the function is exported, and a Promise of the most basic function is realized.
But this Promise is also a synchronous method if you want to use asynchrony in your code, such as:
Let p=new Promise(function(resolve,reject){setTimeout(function(){resolve(' success '); }, 1000); //throw new Error(' Error '); });Copy the code
We need to make it asynchronous:
function Promise(executor){ let self = this; self.status = 'pending'; self.value = undefined; self.reason = undefined; self.onResolvedCallbacks= []; Self.onrejectedcallbacks = []; self.onrejectedCallbacks = []; Resolve (value){if(self.status === 'resolved'){self.status = 'resolved'; self.value = value; self.onResolvedCallbacks.forEach(function(fn){ fn(); }); } } function reject(reason){ if(self.status === 'pending'){ self.status = 'rejected'; self.reason = reason; self.onRejectedCallbacks.forEach(function(fn){ fn(); }); } } try{ executor(resolve,reject); }catch(e){// Reject reject(e); } } Promise.prototype.then=function(onFulfilled,onRejected){ let self = this; if(self.status === 'resolved'){ onFulfilled(self.value); } if(self.status === 'rejected'){ onRejected(self.reason); } if(self.status === 'pending'){ self.onResolvedCallbacks.push(function(){ onFulfilled(self.value); }); self.onRejectedCallbacks.push(function(){ onRejected(self.reason); }); }}; module.exports = Promise;Copy the code
If it’s asynchronous, we can’t use the status status in then to determine which params it’s going to go to, because resolve or reject may not have been executed in then. We’ll add onResolvedCallbacks and onRejectedCallbacks to the Promise instance to store the callback, and if it succeeds, the failure will be undefined by default. The forEach loop array is used to order the methods when called. Native promises can also be used multiple times:
function Promise(executor){ let self = this; self.status = 'pending'; self.value = undefined; self.reason = undefined; self.onResolvedCallbacks= []; self.onRejectedCallbacks= []; function resolve(value){ self.status = 'resolved'; self.value = value; self.onResolvedCallbacks.forEach(function(fn){ fn(); }); } function reject(reason){ self.status = 'rejected'; self.reason = reason; self.onRejectedCallbacks.forEach(function(fn){ fn(); }); } try{ executor(resolve,reject); }catch(e){ reject(e); }}; Promise.prototype.then = function(onFulfilled,onRejected){ let self = this; let promise2; If (self.status === 'resolved'){promise2 = new Promise(function(resolve, resolve)) reject){ try{ let x = onFulfilled(self.value); resolve(x); }catch(e){ reject(e); }}); } if(self.status === 'rejected'){ promise2 = new Promise(function(resolve, reject){ try{ let x = onRejected(self.reason); reject(x); }catch(e){ reject(e); }}); } if(self.status === 'pending'){ promise2 = new Promise(function(resolve, reject){ self.onResolvedCallbacks.push(function(){ try{ let x = onFulfilled(self.value); resolve(x); }catch(e){ reject(e); }}); self.onRejectedCallbacks.push(function(){ try{ let x = onRejected(self.reason); reject(x); }catch(e){ reject(e); }}); }); } return promise2; } module.exports = Promise;Copy the code
And of course the chain call of his THEN doesn’t have a THEN property, so we can tell that every time a Promise is then a new Promise is represented by Promise2, then a new Promise is created and returns to the next THEN. In THEN, no matter the successful return or the failure is destroyed, as long as the result is returned, the success in the next THEN will be followed, and the failure in the next THEN will be followed only when an error occurs. In then, ordinary value can be returned, or a new Promise can be returned. Then ().then. Then (function(){}); Weird usage
function Promise(executor){ let self = this; self.status = 'pending'; self.value = undefined; self.reason = undefined; self.onResolvedCallbacks= []; self.onRejectedCallbacks= []; function resolve(value){ self.status = 'resolved'; self.value = value; self.onResolvedCallbacks.forEach(function(fn){ fn(); }); } function reject(reason){ self.status = 'rejected'; self.reason = reason; self.onRejectedCallbacks.forEach(function(fn){ fn(); }); } try{ executor(resolve,reject); }catch(e){ reject(e); }}; function resolvePromise(p2,x,resolve,reject){ //1. If (p2 === x){reject(new typeError(' circular reference ')); } // Determine whether x is params(determine whether x is object) let called; // if(x! = = = = = null | | typeof x 'object' | | typeof x = = = 'function') {/ / promise as long as the evaluation method of objects are then try {letthen = x.t hen; If (typeof then === 'function'){//then returns {then: XXX}, Then. Call (x,function(y){// Resolve (new Promise()) if(called) return; called = true; resolvePromise(p2,y,resolve,reject); },function(err){ if(called) return; called = true; reject(err); }); }else{ resolve(x); } }catch(e){ if(called) return; called = true; reject(e); }}else{//esle resolve(x); } // this is a big pity. Prototype. Then = function(onFulfilled,onRejected){// Judge onFulfilled is a big pity. Ondepressing === 'function'? onFulfilled : function(value){ return value; } onRejected = typeof onRejected === 'function' ? onRejected : function(err){ throw err; } let self = this; let promise2; If (self.status === 'resolved'){promise2 = new Promise(function(resolve, resolve)) reject){ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }); } if(self.status === 'rejected'){ promise2 = new Promise(function(resolve, reject){ let x = onRejected(self.reason); resolvePromise(promise2,x,resolve,reject); }); } if(self.status === 'pending'){ promise2 = new Promise(function(resolve, reject){ self.onResolvedCallbacks.push(function(){ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }); self.onRejectedCallbacks.push(function(){ let x = onRejected(self.reason); resolvePromise(promise2,x,resolve,reject); }); }); } return promise2; } module.exports = Promise;Copy the code
We define a resolvePromise to handle the result returned by then. If it returns an error message, we use try{}catch(){} reject. Finally, we can execute asynchronously in promises and asynchronously in THEN methods. Just add setTimeout in the slot, and don’t forget to add try{}catch(){} to filter the error message and pass it to reject
function Promise(executor){ let self = this; self.status = 'pending'; self.value = undefined; self.reason = undefined; self.onResolvedCallbacks= []; self.onRejectedCallbacks= []; function resolve(value){ self.status = 'resolved'; self.value = value; self.onResolvedCallbacks.forEach(function(fn){ fn(); }); } function reject(reason){ self.status = 'rejected'; self.reason = reason; self.onRejectedCallbacks.forEach(function(fn){ fn(); }); } try{ executor(resolve,reject); }catch(e){ reject(e); }}; function resolvePromise(p2,x,resolve,reject){ //1. If (p2 === x){reject(new typeError(' circular reference ')); } // Determine whether x is params(determine whether x is object) let called; // if(x! = = = = = null | | typeof x 'object' | | typeof x = = = 'function') {/ / promise as long as the evaluation method of objects are then try {letthen = x.t hen; If (typeof then === 'function'){//then returns {then: XXX}, Then. Call (x,function(y){// Resolve (new Promise()) if(called) return; called = true; resolvePromise(p2,y,resolve,reject); },function(err){ if(called) return; called = true; reject(err); }); }else{ resolve(x); } }catch(e){ if(called) return; called = true; reject(e); }}else{//esle resolve(x); } // this is a big pity. Prototype. Then = function(onFulfilled,onRejected){// Judge onFulfilled is a big pity. Ondepressing === 'function'? onFulfilled : function(value){ return value; } onRejected = typeof onRejected === 'function' ? onRejected : function(err){ throw err; } let self = this; let promise2; If (self.status === 'resolved'){promise2 = new Promise(function(resolve, resolve)) reject){ setTimeout(function(){ try{ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }})}); } if(self.status === 'rejected'){ promise2 = new Promise(function(resolve, reject){ setTimeout(function(){ try{ let x = onRejected(self.reason); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }})}); } if(self.status === 'pending'){ promise2 = new Promise(function(resolve, reject){ self.onResolvedCallbacks.push(function(){ setTimeout(function(){ try{ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }})}); self.onRejectedCallbacks.push(function(){ setTimeout(function(){ try{ let x = onRejected(self.reason); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); }})}); }); } return promise2; } module.exports = Promise;Copy the code