Promise的作用及手写Promise

Promise的作用

Promise 翻译过来就是承诺的意思,这个承诺会在未来有一个确切的答复,并且该承诺有三种状态,分别是: 等待中(pending);完成了 (resolved);拒绝了(rejected)
这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 resolved 后,就不能再次改变
当我们在构造 Promise 的时候,构造函数内部的代码是立即执行的
如:

new Promise((resolve, reject) => {
        console.log('new Promise')
        resolve('success')
    })
    console.log('finifsh')

这里的“new Promise”会在“finifsh”之前执行。

Promise 实现了链式调用,也就是说每次调用 then 之后返回的都是一个 Promise,并且是一个全新的 Promise,原因也是因为状态不可变。如果你在 then 中 使用了 return,那么 return 的值会被 Promise.resolve() 包装。Promise 也很好地解决了回调地狱的问题
它也是存在一些缺点的,比如无法取消 Promise,错误需要通过回调函数捕获

手写Promise

内容较多,谨慎观看

<script>
    //定义三个常量,表示状态
    const PENDING = 'pending';//等待
    const RESOLVED = 'resolved';//成功
    const REJECTED = 'rejected';//失败

    function MyPromise(fn) {
        const that = this;//创建常量,因为代码可能会异步执行,用于获取正确的this的对象;
        that.state = PENDING;//promise的初始状态为pending
        that.value = null;//value变量用于保存resolve或者reject中传入的值
        that.resolvedCallbacks = [];//用于保存then中的回调
        that.rejectedCallbacks = [];//用于保存then中的回调
        //下一步完善resolve和reject函数
        //resolve和reject函数,
        // 首先都要判断当前状态是否为pending,因为根据promise的规范规定只有pending状态才可以改变状态
        //其次改变当前的状态,是resolved或者rejected,并将传入的值赋值个value
        //最后遍历回调函数并执行
        function resolve(value) {
            // if(that.state === PENDING){
            //     that.state = RESOLVED;
            //     that.value = value;
            //     that.resolvedCallbacks.map(cb => cb(that.value));
            // }
            //为符合promise/A+规范,对代码进行改造
            //首先判断传入的值是否为promise类型
            //其次为保证函数的执行顺序,需要将两个函数体代码使用setTimeout包裹起来
            if(value instanceof MyPromise){
                return value.then(resolve,reject)
            }
            setTimeout( () => {
                if(that.state === PENDING){
                    that.state = RESOLVED;
                    that.value = value;
                    that.resolvedCallbacks.map(cb => cb(that.value));
                }
            },0)
        }
        function reject(value) {
            // if(that.state === PENDING){
            //     that.state = REJECTED;
            //     that.value = value;
            //     that.rejectedCallbacks.map(cb => cb(that.value));
            // }
            //为符合promise/A+规范,对代码进行改造
            setTimeout( () => {
                if(that.state === PENDING){
                    that.state = REJECTED;
                    that.value = value;
                    that.rejectedCallbacks.map(cb => cb(that.value));
                }
            },0)
        }
        //下一步完善执行fn函数
        //首先执行传入的参数并将之前的resolve和reject当做参数传进去
        //其次在执行函数的过程中可能会遇到错误,需要捕获错误并执行reject函数
        try{
            fn(resolve,reject)
        }catch (e) {
            reject(e)
        }
    }
    //实现then函数
    //首先判断两个参数是否为函数类型,因为两个参数是可选参数
    //当参数不是函数类型时,需要创建一个函数赋值个对应的参数,同时也实现了透传
    //最后判断状态,当状态不是pending时,就去执行对应的函数。如果状态是pending时,就往回调函数中push进函数
    MyPromise.prototype.then = function (onFulfilled,onRejected) {
        // const that = this;
        // onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
        // onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r};
        // if(that.state === PENDING){
        //     that.resolvedCallbacks.push(onFulfilled);
        //     that.rejectedCallbacks.push(onRejected);
        // }
        // if(that.state === RESOLVED){
        //     onFulfilled(that.value);
        // }
        // if(that.state === REJECTED){
        //     onRejected(that.value);
        // }
        //为符合promise/A+规范,对代码进行改造
        let newPromise;//新增一个变量,每一个then函数都会返回一个新的promise对象,该变量用于保存新的返回对象
        const that = this;
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason;};
        if(that.state === PENDING){
            return (newPromise = new MyPromise((resolve,reject) => {//返回一个新的promise对象,并传入一个函数
                that.resolvedCallbacks.push( () => {//往回调函数push新的函数
                    try{//执行过程中,可能遇到错误,使用try...catch包裹
                        const x = onFulfilled(that.value);//执行函数时,返回一个x
                        resolutionProcedure(newPromise,x,resolve,reject);//执行promise解决过程
                    }catch (reason) {
                        reject(reason)
                    }
                });
                that.rejectedCallbacks.push( () => {
                    try{
                        const x = onRejected(that.value);
                        resolutionProcedure(newPromise,x,resolve,reject);
                    }catch (reason) {
                        reject(reason)
                    }
                })
            }))
        }
        if(that.state === RESOLVED){
            return (newPromise = new MyPromise((resolve,reject) => {
                setTimeout( () => {
                    try {
                        const x = onFulfilled(that.value);
                        resolutionProcedure(newPromise,x,resolve,reject);
                    }catch (reason) {
                        reject(reason)
                    }
                })
            }))
        }
        if(that.state === REJECTED){
            return (newPromise = new MyPromise((resolve,reject) => {
                setTimeout( () => {
                    try {
                        const x = onRejected(that.value);
                        resolutionProcedure(newPromise,x,resolve,reject);
                    }catch (reason) {
                        reject(reason)
                    }
                })
            }))
        }
    };
    function resolutionProcedure(newPromise,x,resolve,reject) {
        if (newPromise === x){//规定newPromise不能与x相等
            return reject(new TypeError('Error'));
        }
        if(x instanceof MyPromise){//如果x为promise时;第一,当x处于等待状态,promise需保持等待状态直到x被执行或拒绝
            x.then((value) => {//第二,当x处于其他状态时,则用相同的值处理promise
                resolutionProcedure(newPromise,value,resolve,reject);
            },reject)
        }
        let called = false;//创建一个变量,用于判断是否已经调用过函数
        if(x !== null && (typeof x === 'object' || typeof  x === 'function')){//判断x是否为对象或者是函数
            try{//如果x是对象或者函数
                let then = x.then;//将x.then赋值给then
                if(typeof then === 'function'){//判断then的类型是否为函数
                    then.call(//如果then为函数类型,
                        x,//就将 x 作为函数的作用域 this 调用之,并且传递两个回调函数作为参数
                        y => {//第一个参数叫做 resolvePromise,需要判断是否已经执行过函数,然后进行相应的逻辑
                            if(called) return;
                            called = true;
                            resolutionProcedure(newPromise,y,resolve,reject);
                        },
                        e => {//第二个参数叫做 rejectPromise,需要判断是否已经执行过函数,然后进行相应的逻辑
                            if(called) return;
                            called = true;
                            reject(e);
                        }
                    )
                }else {
                    resolve(x);//如果then不是函数类型,将x传入resolve中
                }
            }catch (e) {//将错误抛出
                if (called) return ;
                called = true;
                reject(e);
            }
        }else {
            resolve(x);//如果x不是对象或者函数,将x传入resolve中
        }
    }
    new MyPromise((resolve,reject) => {
        setTimeout( () => {
            resolve(1)
        },0)
    }).then(value => {
        console.log(value);//1
    })
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在提供的代码中,已经实现了一个自定义的`promiseAll`函数来模拟`Promise.all`的功能。以下是对代码的解释和改进建议。 首先,在代码中定义了`isReadFile`函数,它返回一个`Promise`对象,用于读取文件。这是一个很好的实践,可以将其作为`Promise`的包装器来处理异步操作。 接着,在测试代码中创建了三个`Promise`对象`p1`,`p2`和`p3`,分别用于读取文件`1.txt`,`2.txt`和`3.txt`。然后将这些`Promise`对象作为参数传递给`promiseAll`函数。 需要注意的是,由于在读取文件`3.txt`时发生了错误,因此`p3`应该被拒绝,并返回一个错误消息。 接下来,可以通过以下方式改进代码: 1. 在错误处理中使用`reject`函数来传递实际的错误对象,而不仅仅是一个字符串错误消息。这样可以更好地捕获和处理错误。 2. 在`promiseAll`函数中,使用`Promise.resolve`来确保传递给`promiseAll`的参数是一个`Promise`对象数组。这样可以在实际参数是一个`Promise`对象时,不用手动包装成数组。 3. 在`promiseAll`函数中,使用`Promise.all`来处理传入的`promises`数组。这样可以更好地处理并发的异步操作,并且能够正确处理其中一个`Promise`对象失败的情况。 以下是改进后的代码示例: ```javascript const fs = require('fs'); function isReadFile(file) { return new Promise((resolve, reject) => { fs.readFile(file, "utf8", (err, data) => { if (err) { return reject(err); } resolve(data); }); }); } function promiseAll(promises) { return Promise.all(promises); } let p1 = isReadFile('1.txt'); let p2 = isReadFile('2.txt'); let p3 = isReadFile('3.txt'); promiseAll([p1, p2, p3]).then( res => { console.log(res); }, err => { console.log(err); } ); ``` 以上代码中,已经对错误处理进行了改进,并且使用了`Promise.resolve`和`Promise.all`来优化`promiseAll`函数的实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [手写promise.all](https://blog.csdn.net/weixin_54217534/article/details/125471928)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值