Why use Promise?

We do front-end development, for asynchronous task processing is more headache, if there is such a small example of asynchronous task:

Function start(){setTimeout(function(){return "here is my result "; },3000) } console.log(start()); //undefinedCopy the code

So we print undefined, and I think we all know why it’s undefined. So we usually use the callback function to get the value returned by the asynchronous task

Function start(fn) {setTimeout(function () {fn(" here is my result ")}, 3000)} start(function (data) {console.log(); a(data); Function a(data) {console.log(); function a(data) {console.log(); b(data); Function b(data) {console.log(); function b(data) {console.log(); }}})Copy the code

In this way, the layers of our code are nested layer by layer. If there are fewer layers, it is ok, but if there are more layers, the readability of the code will be poor, which is not conducive to the later maintenance of developers. In this scenario, promises occur;

A constructor that implements a Promise;

We won’t cover the use of promises here, but you can see the documentation es6.ruanyifeng.com/#docs/promi… We implement our own Promise constructor.

function MyPromise(excutor){ this.status="pending"; // The current state is pending this.data=undefined; // This. CallBack =[]; If (this.status!){// If (this.status!){if(this.status!){// If (this.status! ='pending'){ return; } this.status="resolve"; this.data=value; // Here we use a macro task to implement our asynchronous callback function to make sure we get the value of the callback, SetTimeout (()=>{this.callback. forEach(item=>{console.log(" execute our callBack here "); })})} function reject(reason){if(this.status! ='pending'){ return; } this.status="reject"; this.data=value; SetTimeout (()=>{this.callback.foreach (item=>{console.log(" execute our callBack here "); Resolve.bind (this),reject. Bind (this)); resolve.bind(this); }catch (err) {reject. Call (this,err); }}Copy the code

Implement the.then method

The then method can pass in two callback functions, the first a successful callback and the second a failed one

MyPromise.prototype.then=function(onResolve,onReject){ let that=this; // If no success callback is passed in, the value of the callback is returned by default, because there is a concept of value-throughness in Promise let onResolve=typeof onResolve=="function"? onResolve:value=>value; // If no failed callback is passed, assign a function that throws an exception let onReject=typeof onReject=="function"? onReject:err=>{ throw err; Return new MyPromise((resolve,reject)=>{function handler(on){// get the value let returned by the callback function a=on(that.data); If (a instanceof MyPromise){a.tenn (data=>{resolve(data); },err=>{ reject(err); }) }else{ resolve(a); }} // If the current state is pending, the callBack function needs to be stored in the callBack, If (that.status=="pending"){that.callback.push ({onresolve:function(){handler(onresolve); }, onreject:function(){ handler(onReject); }else if(that.status=="resolve"){setTimeout(()=>{handler(onResolve); }else{setTimeout(()=>{handler(onReject)})}})}Copy the code

We can now complete our Promise constructor:

function MyPromise(excutor){ this.status="pending"; // The current state is pending this.data=undefined; // This. CallBack =[]; If (this.status!){// If (this.status!){if(this.status!){// If (this.status! ='pending'){ return; } this.status="resolve"; this.data=value; SetTimeout (()=>{this.callback. forEach(item=>{item.onresolve(value); // We use a macro task to implement our asynchronous callBack function. / / + + + + + + + + + + + + + + + + + + + + + + + +})})} function reject (reason) {/ / failure callback if (this. The status! ='pending'){ return; } this.status="reject"; this.data=value; setTimeout(()=>{ this.callBack.forEach(item=>{ item.onreject(reason); / / + + + + + + + + + + + + + + + + + + + + + + + + + +})})} try {/ / perform constructor, and at the same time we also need to monitor the constructor executes, whether an error excutor (resolve) the bind (this), reject the bind (this));  }catch (err) {reject. Call (this,err); }}Copy the code

Implementing catch methods

With the then method, the catch method is simpler to execute the failed callback directly

MyPromise.prototype.catch = function (onReject) {
     return this.then(undefined, onReject);
}
Copy the code

Implement the resolve static method

Mypromise.resolve = function (value) {return new MyPromise((resolve, reject) => {//promise. If (value instanceof MyPromise) {value. Then (data => {resolve(data); }).catch(err => { reject(err); })} else {//promise.resolve (value); }})}Copy the code

Implement the reject static method

Reject = function (value) {//promise. Reject = function (value) {// Promise. reject) => { reject(value); })}Copy the code

Implement all static methods

Mypromise. all = function (arr = []) {//promise.all: Return new MyPromise((resolve, reject) => {var list = []; var n = 0; arr.forEach((item, index) => { MyPromise.resolve(item).then(data => { n++; list.push(data); if (n === arr.length) { resolve(list) } }).catch(err => { reject(err); })})})}Copy the code

Implement the Race static method

MyPromise.race = function (arr = []) {
            return new MyPromise((resolve, reject) => {
                arr.forEach(item => {
                    item.then(data => {
                        resolve(data)
                    }).catch(err => {
                        reject(err)
                    })
                })
            })
}
Copy the code

Thank you! .