关闭

手写Promise

时间: 2021-01-17阅读: 56标签: Promise

Promise的用法 :

let p = new Promise(function(resolve, reject){
    console.log(111)
    setTimeout(function(){
        resolve(2)
    }, 1000)
})
p.then(function(res){
    console.log('suc',res)
},function(err){
    console.log('err',err)
})

可以看到new了一个Promise,里面有一个回调函数,回调函数里有2个参数,分别又是另外2个函数。其实里面很多也都是回调函数的封装调用。

const [PENDING,RESOLVED,REJECTED]=["PENDING","RESOLVED","REJECTED"];`

class Promise1 {
    
    constructor(executor){
        state = PENDING;
        value = undefined;
        reason = undefined;
        
        resolve = (value) => {
            if(this.state === PENDING){
                this.state = RESOLVED;
                this.value = value;
            }
        }
        reject = (reason) => {
            if(this.state === PENDING){
                this.state = REJECTED;
                this.value = reason;
            }
        }
        
        try{
            executor(this.resolve,this.reject)
        }catch(e){
            reject(e)
        }
    }
 }

测试一下执行情况:

let p1 = new Promise1((resolve,reject)=>{//function:executor
    console.log(111)
    setTimeout(()=>{
        resolve(111)//this.resolve,直接传参调用
    }, 1000)
})

下面就是then了

class Promise1 {
    constructor(executor){
        ...
        onResolvedCallbacks=[]; //then,pending里先存起来
        onRejectedCallbacks=[];

        ...

        resolve = (value) => {
            if(this.state === PENDING){
                ...
                //executor里如果是异步会把then里存起来,然后executor走完了resolved的话,会再调then里回调函数
                this.onResolvedCallbacks.forEach(fn => fn(value))
            }
        }
        reject = (reason) => {
            if(this.state === PENDING){
                ...
               this.onRejectedCallbacks.forEach(fn => fn(reason))
            }
        }
    }
    
    then(onResolved,onRejected){
        onResolved = typeof onResolved === 'function' ? onResolved : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {
            throw reason
        };
        
        switch(this.state){
            case RESOLVED : //状态变了,就直接把结果给出去
                onResolved(this.value);
            case REJECTED :
                onRejected(this.reason);
            case PENDING : 
            //如果是pending的话,说明executor还没走完,先存起来,走完再调用
                this.onResolvedCallbacks.push(onResolved);
                this.onRejectedCallbacks.push(onRejected)
        }
    }
}

测试一下 :

let p2 = new Promise1((resolve, reject) => {
    setTimeout(()=>{
        resolve(222)
    }, 1000)
})
p2.then(res => console.log(res, 'res')) //222

链式调用:

class Promise1 {
    ...
    
    
    then(onResolved,onRejected){
        ...
        //返回一个promise1
        let newPromise=new Promise1((resolve,reject)=>{
            switch(this.state){
                case RESOLVED : //状态变了,就直接把结果给出去
                    setTimeout(()=>{//then,放后面处理
                        try{
                        let reValue=onResolved(this.value);
 rePromise(newPromise,reValue,resolve,reject)
                        }catch(e){reject(e)}
                    },0)
                    
                case REJECTED :
                    setTimeout(()=>{
                        try{
                            let reValue=onRejected(this.reason);
                            rePromise(newPromise,reValue,resolve,reject)
                        }catch(e){reject(e)}
                    },0)
                    
                case PENDING : 
                //如果是pending的话,说明executor还没走完,先存起来,走完再调用
                    this.onResolvedCallbacks.push(()=>{
                        setTimeout(()=>{
                            try{
                                let reValue=onResolved(this.value);
 rePromise(newPromise,reValue,resolve,reject)
                            }catch(e){reject(e)}
                        },0)
                    });
                    this.onRejectedCallbacks.push(()=>{
                        setTimeout(()=>{
                            try{
                                let reValue=onRejected(this.reason);
                            rePromise(newPromise,reValue,resolve,reject)
                            }catch(e){reject(e)}
                        },0)
                    })
            }
        })
        return newPromise;
    }
}

//newPromise:新的promise1对象,reValue:上一个then的返回值,newPromise.resolve,newPromise.reject
function rePromise(newPromise,reValue,resolve,reject){
    //相当于把自己return出去了,let p2 = p.then(res => p2);
    if(newPromise === reValue){
        reject(new TypeError('循环了'))
    }
    if(reValue !== null && (typeof reValue === 'object' || typeof reValue === 'function')){
        try{
    //判断一下reValue是不是promise1,是个对象,还带有then函数
    //如果有then并是个函数,就调then; 
            let then = reValue.then;
            if(typeof then === 'function'){
                then.call(reValue, res=>{
                    resolve(res)
                },err=>{
                    reject(err)
                })
            }else{//then不是函数,直接用resolve返回值
                resolve(reValue)
            }
        }catch(e){
            reject(e)
        }
    }else{//只是个普通值
        resolve(reValue)
    }
}

测试一下:

p3.then(res => {
    console.log(res)
    return new Promise1((resolve, reject) => {
        resolve('p3')
    })
}).then(res => console.log(res, 'pp3'))//p3

但还有个问题

...

function rePromise(newPromise,reValue,resolve,reject){
    ...
    let called;//是否调用过,防止多次调用
    if(reValue !== null && (typeof reValue === 'object' || typeof reValue === 'function')){
        try{
   
            let then = reValue.then;
            if(typeof then === 'function'){
                then.call(reValue, res=>{
                    if(called) return;
                    called = true;
                   //promise1就继续下一个,直到then走完,变成普通的值 
                   rePromise(newPromise,res,resolve,reject)
                },err=>{
                    if(called) return;
                    called = true;
                    reject(err)
                })
            }else{//then不是函数,直接用resolve返回值
                resolve(reValue)
            }
        }catch(e){
            if(called) return;
            called = true;
            reject(e)
        }
    }else{//只是个普通值
        resolve(reValue)
    }
}

测试一下

    let p1=new Promise1((resolve,reject)=>{
        resolve(111)
    })
    let p2=p1.then(res=>{console.log(res,'p1')},err=>console.log(err,'p1'));
    p2.then(res=>console.log(res,'p2'))
    .then(res=>console.log(res,'p3))

还有其它属性:

class Promise1 {
    ...
    catch(onReject){
        return this.then(null,onReject)
    }
    defer(){
        let defer={};
        defer.promise=new Promise1((resolve,reject)=>{
            defer.resolve=resolve;
            defer.reject=reject;
        })
        return defer;
    }
    deffered(){
        return this.defer;
    }
    all(promises){
        return new Promise1((resolve,reject)=>{
            let done=gen(promises.length,resolve);
            for(let i=0;i<promises.length,i++){
                promises[i].then(res=>{
                    done(i,res)
                },reject)
            }
        })
    }
    race(promises){
        return new Promise1((resolve,reject)=>{
            for(let i=0;i<promises.length;i++){
                promises[i].then(resolve,reject)
            }
        })
    }
    resolve(value){
        return new Promise1((resolve,reject)=>{
            resolve(value)
        })
    }
    reject(reason){
        return new Promise1((resolve,reject)=>{
            reject(reason)
        })
    }
}

function gen(times,cb){
    const result=[];
    let count=0;
    return (i,data)=>{
        result[i]=data;
        count+=1;
        if(count===times){
            cb(result)
        }
    }
}
站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/10159

把 Node.js中的回调转换为Promise

在 ES6 中引入了 Promise 作为这些问题的解决方案。最后通过引入 async/await 关键字来提供更好的体验并提高了可读性。即使有了新的方法,但是仍然有许多使用回调的原生模块和库

你真的了解 Promise 吗?Promise 必知必会(十道题)

Promise 想必大家十分熟悉,想想就那么几个 api,可是你真的了解 Promise 吗?本文根据 Promise 的一些知识点总结了十道题,看看你能做对几道。

ES6入门之Promise对象

Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件更合理、更强大。简单来说就是一个容器,里面保存着某个未来才会结束的事件(也就是异步操作)的结果。从语法上来讲,Promise是一个对象

Promise原理探究及实现

作为ES6处理异步操作的新规范,Promise一经出现就广受欢迎。面试中也是如此,当然此时对前端的要求就不仅仅局限会用这个阶段了。下面就一起看下Promise相关的内容。还是简单回顾下Promise是什么以及怎么用

掌握 Promise 的逻辑方法

Promise 是 ES2015 新增的对象:Promise 对象有几个组合方法,可以将多个承诺合并成一个进行处理,分别是 Promise.all, Promise.race, Promise.allSettled, Promise.any,这些方法都可以接收一组承诺,返回一个新的承诺

简单模仿实现 Promise 的异步模式

这篇文章是考虑如何自己实现一个简单 Promise,用以理解 Promise。和原生 Promise的调用方法一样,支持链式调用,本文实现的方法只能用于参考Promise的原理,还有很多特性没有实现,比如 race,all 方法的实现。

这几个Promise的输出到底是?

我们使用构造函数方法创建一个Promise实例,立即使用 reject 回调触发一个错误。catch处理程序的工作方式类似于DOM的 .addeventlistener(事件、回调)或事件发射器的 .on(事件、回调),其中可以添加多个回调。每个回调都具有相同的参数。

Promise 原理解析与实现(遵循Promise/A+规范)

Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一,Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数

从 callback 到 promise

说起回调(callback),那可以说是 JS 最基础的异步调用方式,是 JS 为解决阻塞请求而量身定制出的一种设计模式,在 JS 或是说前端大潮中有着举足轻重的影响

动手写一个Promise

现在Promise用的比较频繁了,如果哪天突然不用了,可能逻辑就不好厘清了,回调没的说是一大把,Promise这个东西很神奇,用起来舒服,若自己写一下,恐怕还真不简单,关键就一个字“绕”,绕过了也就好了

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!