js手写一个实现一个简单的promise__小前端chenMr

1.首先来看一下promise常用场景

function chenPromise (arg) {
   return new Promise (resolve, reject) {
      if () {
          doSomeThing(arg)
          resolve(val)
      } else {
          reject(val)
      }
   }
 }
chenPromise(arg).then(((val)
=> {}, (err) =>{})
知识兔

2.了解promise状态

1.常规分三种:PENDING, RESOLVED, REJECTED

2.一开始promise状态是PENDING,当调用了resolve()之后promise的状态就被固定了即成功时的状态RESOLVED,当调用了reject()之后promise状态就被成了REJECTED了

3.上面说了一旦调用了reject()或者resolve()状态就不能被改变了,这一点也可以算是promise的缺陷吧

4.代码是怎么做到状态从pending到resolove就不会被改变了呢可通过代码如下

_resolve(){
       window.addEventListener('message', (val)=>{ if (this.status !== KPromise.PENDING) return // 当状态已经被固定了就不会往下执行了 this.status = KPromise.RESOLVED // 当执行这个函数的时候状态就已经被固定了 this.value = val let handler; while(handler = this.resolveQueues.shift()){ handler(this.value) } })
}
知识兔

3.控制.then()在resolve()后面执行

实现思路:当调用.then(resolvehandle,rejecthandle)方法时将resolvehandle和rejecthandle分别push到一个数组中,当resolve()执行时,遍历两个数组unshift()一次一队列先进先出方式依次执行

then(resolveHandler, rejectHandler) {
       
         this.resolveQueues.push(resolveHandler)
         this.rejectQueues.push(rejectHandler)
  }

reject(){
知识兔
  let handler;
   while(handler = this.rejectQueues.shift()){ // 执行以队列方式(先进先出方式)执行被注册函数
    handler(this.value)
         }
}

resolve () {
  
知识兔
let handler;
   while(handler = this.resolveQueues.shift()){ // 执行以队列方式(先进先出方式)执行被注册函数
    handler(this.value)
     }
}
知识兔

3.实现promise先于setTimeout执行

setTimeout(() => {console.log(123)}, 100)

promise().resolve().then(() => {console.log(456)})
 
结果是先输出456 在输出123

知识兔
这里实现涉及事件循环以及异步任务的宏认为和微任务执行顺序,通过微任务先于宏认为先执行机制来实现,具体可以通过h5新增的messge方法来达到如下

resolve(val) {
    window.addEventListener('message', (val)=>{ // 这里涉及到宏任务和微任务的区别,实现让promises里面的方法是先于setTimeout执行的
            if (this.status !== KPromise.PENDING) return // 当状态已经被固定了就不会往下执行了
            this.status = KPromise.RESOLVED  // 当执行这个函数的时候状态就已经被固定了

            this.value = val
    
            let handler;
            while(handler = this.resolveQueues.shift()){ // 执行以队列方式(先进先出方式)执行被注册函数
                handler(this.value)
            }
        })
        window.postMessage('') // h5新增

        this._finally(this.value)
}

_rejected(val) {
        window.addEventListener('message',()=>{ // 这里涉及到宏任务和微任务的区别,实现让promises里面的方法是先于setTimeout执行的
            this.status = KPromise.REJECTED 
                let handler;
                while(handler = this.rejectQueues.shift()){ // 执行以队列方式(先进先出方式)执行被注册函数
                handler()
                }
        })
        window.postMessage('') // node 中有prosee.nexTick()

        this._finally(this.value)
    }

4.实现promise链式调用如promise.then().then()以及实现

then(resolveHandler, rejectHandler) {        // 实现连续的.then().then().then()调用,通过.then()返回新的promise供后续.then调用        return new  KPromise((resolve, reject) =>{ // 外层包装了一层promise            function newResolvedHandler(val) {                if(typeof resolveHandler === 'function') { // 判断第一个是否是函数                    let result = resolveHandler(val) // 第一参数也就是前一个.then先执行                                        if(result instanceof KPromise) {                        result.then(resolve, reject)                    } else {                        resolve(result)                    }                } else {                    resolve(val)                }                          }            function newRejectHandler(val) {                if (typeof rejectHandler === 'function'){                    let result = rejectHandler(val) // 第二个参数就是前一个.then(,reject())第一reject先执行                           if(result instanceof KPromise) {                            result.then(resolve, reject)                            } else {                               reject(result)                            }                } else {                    reject(val)                }                            }            this.resolveQueues.push(newResolvedHandler)            this.rejectQueues.push(newRejectHandler)        })    }

上面所述都是个人认为有坑的地方:下面附上完整代码

class CPromise {    // 定义三个状态常量    static PENDING = 'PENDING';    static RESOLVED = 'RESOLVED';     static REJECTED = 'REJECTED';     constructor( handler ) {        if ( typeof handler !== 'function' ) throw new TypeError('Promise resolver undefined is not a function');        this.resolvedQueues = []; // 定义一个空数组,注册保存调用.then(resolve, )方法传递的第一个resolve函数        this.rejectedQueues = []; // 定义一个空数组,注册保存调用.then(, reject)方法传递的二个reject函数        this.finayllyQueues = []; // 定义一个空数组,注册保存调用.finally(finally)这里的finally函数,        this.status = CPromise.PENDING;        this.value;        handler( this._resolve.bind(this), this._reject.bind(this) ); // 通过bind改变当前函数this执行,然后就可以使用this.status,RESOLVED等常量    }    _resolve(val) {        // setTimeout(_=>{                    // }, 0);        window.addEventListener('message', _=>{             // message是h5的新特性,这里涉及到异步中的宏认为和微任务执行优先级,这里message事件属于微任务优先于setTimeout执行,例如下面的demo            // setTimeout(() => {console.log(123)}, 0)             // CPromise.resolve().then((res)=>{console.log(456)})            // 上面代码先输出456然后输出123                        if (this.status !== CPromise.PENDING) return; // 这里的判断是防止当状态是resolved或者是rejected也就是状态被固定时状态被改变            // console.log('_resolve');            this.status = CPromise.RESOLVED; // 将状态置位resolve 并且不允许改变            this.value = val;            let handler;            while( handler = this.resolvedQueues.shift() ) { // 执行以队列方式(先进先出方式)执行被注册函数                handler(this.value); // 执行.then里面第一参数即resolve方法            }            this._finally(this.value); // 最后执行finally方法        });        window.postMessage(''); // 触发上面的message事件    }    _reject(val) {        // setTimeout(_=>{                    // }, 0);        window.addEventListener('message', _=>{            if (this.status !== CPromise.PENDING) return; // 这里的判断是防止当状态是resolved或者是rejected也就是状态被固定时状态被改变            this.status = CPromise.REJECTED; // 将状态置位rejected 并且不允许改变            this.value = val;            let handler;            while( handler = this.rejectedQueues.shift() ) { // 执行以队列方式(先进先出方式)执行被注册函数                handler(this.value); // 调用.then里面第二个参数即rejected方法            }            this._finally(this.value); // 最后执行finally方法        });        window.postMessage('');    }    _finally() { // 通过此方法触发在finally方法注册的finayllyQueues数组里面的所有方法        window.addEventListener('message', _=>{             this.status = CPromise.REJECTED;            let handler;            while( handler = this.finayllyQueues.shift() ) { // 执行以队列方式(先进先出方式)执行被注册函数                handler(this.value);            }        });        window.postMessage('');    }    then( resolvedHandler, rejectedHandler ) {        return new CPromise( (resolve, reject) => { // 这里返回以个promise是为了满足.then().then()链式调用            function newResolvedHandler(val) {                if (typeof resolvedHandler === 'function') { // 如果then第一个参数是函数                    let result = resolvedHandler(val);                    if (result instanceof CPromise) { // 如果函数返回是一个promise                        result.then(resolve, reject);                    } else {                        resolve(result);                    }                } else {                    resolve(val);                 }            }            function newRejectedHandler(val) {                if (typeof rejectedHandler === 'function') { // 如果then第一个参数是函数                    let result = rejectedHandler(val);                    if (result instanceof CPromise) { // 如果函数返回是一个promise                        result.then(resolve, reject);                    } else {                        reject(result);                    }                } else {                    reject(val);                }            }            this.resolvedQueues.push(newResolvedHandler); // push到相应数组等到resolve时遍历执行里面函数            this.rejectedQueues.push(newRejectedHandler); // push到相应数组等到resolve时遍历执行里面函数        } );    }    catch(rejectedHandler) {        return this.then(undefined, rejectedHandler); // 这里的catch实现其实是调用了then方法来实现    }    finally(finallyHandler) {        this.finayllyQueues.push(finallyHandler);    }    static resolve(val) { // 静态resolve方法 通过promise.resolve()方式调用        return new CPromise(resolve => {            resolve(val);        });    }    static reject(val) { // 静态reject方法 通过promise.reject()方式调用        return new CPromise((resolve, reject) => {            reject(val);        });    }    static all(iterator) {        let len = iterator.length;        let i = 0;        let vals = [];        return new CPromise( (resolve, reject) => {            iterator.forEach(it => {                it.then(val => {                    i++;                    vals.push(val);                    if (i === len) {  // 当所有promise都被执行完了,才resolve结束                        resolve(vals);                    }                }).catch(e=> {                    reject(e);                });            });        } );    }    static race(iterator) { // iterator 是一个promise数组        return new CPromise((resolve, reject) => {            iterator.forEach(it => {                it.then(val => { // 返回封装成promise的数组,只要有一个被resolve就行                    resolve(val);                }).catch(e=> {                    reject(e);                });            });        })    }}

有不对的地方,希望评论指正,个人看了些东西然后写下的一点点理解希望能对你有所帮助!!!

计算机