JS手写Promise以及promise.all方法

Promise是处理异步的一种方式,解决了回调地狱的问题。

Promise有三种状态:

1.pending(待定):初始状态。

2.fulfilled(已兑现):表示异步操作成功,返回一个返回值。

3.rejected(已拒绝):表示异步操作失败,返回一个错误原因。

状态转换:可以从pending转换到fulfiied,从pending转换到rejected。一旦转换成功,状态就不可再发生改变。

常用方法:

1.Promise.resolve():将给定的一个值转换为Promise。如果本身就是Promise,那么直接返回,如果该值是一个thenable对象,那么将调用其then方法及其两个回调函数;

2.Promise.reject():返回一个已拒绝(rejected) 的Promise对象,拒绝原因为给定的参数。

3.Promise.all():接受一个Promise可迭代对象作为输入,并返回一个Promise。当所有的Promise都被兑现时,返回的Promise也将被兑现,并返回一个包含所有兑现值的数组。输入的任何被拒绝,返回的也将被拒绝。

接下来就是基本结构:

class myPromise{
    constructor(executer) {
        this.state = 'pending' //初始状态为pending
        this.value = undefined  //成功的值
        this.reason = undefined  //失败原因
        this.onFulfilledCallbacks = []; //成功回调函数数组
        this.onRejectedCallbacks = []  //失败回调函数数组

        const resolve = value => {  //resolve函数,用于改变状态,从pending到fulfilled,并记录成功的值
            if(this.state === 'pending') {  //只有在pending状态下才能进行状态转变
                this.state = 'fulfilled'
                this.value = value
                this.onFulfilledCallbacks.forEach(fn => fn())  //执行每一个回调函数
            }
        }

        const reject = reason => {  //reject函数,用于改变状态
            if(this.state = 'pending') {  //严谨一点
                this.state = 'rejected'
                this.reason = reason
                this.onRejectedCallbacks.forEach(fn => fn())  //执行每一个失败回调函数
            }
        };
    try {
        executor(resolve,reject);
    } catch (err){
        reject(err)
    }
    }
}

.then方法

myPromise.prototype.then = function(onFulfilled, onRejected) {
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value  //设置默认回调函数,确保函数类型,如果没有则使用默认处理函数
            onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}

            let promise2 = new myPromise((resolve,reject) => {  //创建新的promise用于链式调用
                if(this.state === 'fulfilled' || this.state === 'rejected') {   //判断状态,如果为fulfilled,执行成功回调,反之则执行失败回调
                    setTimeout(() => {
                        try {  //获取成功回调的返回值
                            let result = this.state ==='fulfilled' ? onFulfilled(this.value) :onRejected(this.reason)
                            resolvePromise(promise2, result, resolve, reject) //处理返回值确定promise2的状态
                        } catch (e) {
                            reject(e) //如果执行过程出错就reject
                        }
                    }, 0)
                }

                if(this.state === 'pending') {   //如果状态为pending,把回调函数存储起来
                    this.onFulfilledCallbacks.push(()=> {
                        setTimeout(() => {
                            try {
                                let x = onFulfilled(this.value)
                                resolvePromise(promise2, x, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        },0)
                    })
                    this.onRejectedCallbacks.push(() => {
                        setTimeout(() => {
                            try {
                                let x = onRejected(this.reason)
                                resolvePromise(promise2, x, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        },0)
                    })
                }

                return promise2
            })
        }

resolvePromise方法,用于处理then方法中返回的结果,以界定新的promise状态

function resolvePromise(promise2, x, resolve, reject) {
            if(promise2 === x) {  //如果一样,抛出TypeError防止自循环
                return reject(new TypeError('changing cycle detected from promise'))
            }
​
            let called  //如果X是对象或者数组
            if(x != null && (typeof x === 'object' || typeof x === 'function')) {
                try {
                    let then = x.then  //取出x的then方法
                    if(typeof then === 'function') {  //如果then是函数,调用,传入resolvePromise和reject函数
                        then.call(x,y => {
                            if(called) return
                            called = true
                            resolvePromise(promise2, y, resolve, reject)
                        }, r=> {
                            if(called) return
                            called = true
                            reject(r)
                        })
                    } else {
                        reslove(x) //如果x不是,以x为值fulfill promise2
                    }
                } catch(e) {
                    if(called) return 
                    called = true
                    reject(e)
                }
            } else {
                resolve(x)
            }
        }

resolve,reject方法用于快速生成一个promise对象

 myPromise.prototype.resolve = function(value) {
            return new myPromise((resolve,reject) => {
                resolve(value)
            })
        }
​
 myPromise.prototype.reject = function(reason) {
            return new myPromise((resolve,reject) => {
                reject(reason)
            })
        }
​

.all()方法,传入数组promise,将多个promise包装成一个新的promise,且只有多个全部成功,新实例才会成功

myPromise.prototype.all = function(promises) {
            return new myPromise((resolve, reject) => {  //返回一个新的promise
                let result = []  //存储每一个promise的结果
                let count = 0  //记录完成的数量
​
                function processresult(index, data) {  //处理单个promise
                    result[index] = data
                    count++
                    if(count === promises.length) {  //如果所有promise全部完成,resolve一个新的promise
                    resolve(result)
                    }
                }
​
                for(let i=0;i<promises.length;i++) {  //遍历数组,处理结果
                    promises[i].then(data => {
                       processresult(i,data)
                    }, reject)
                }
            })
        }

手写实现 `Promise.all` 方法,可以按照以下步骤进行操作: 1. 创建一个新的 Promise 对象,并返回它。 2. 在内部创建一个数组 `results`,用于存储每个传入的 Promise 对象的结果。 3. 使用 `Array.from` 方法将传入的参数(可以是数组或类数组对象)转换为一个真正的数组。 4. 遍历数组中的每个 Promise 对象,使用 `Promise.resolve` 方法将其转换为一个 Promise 对象。 5. 对于每个 Promise 对象,使用 `.then` 方法来处理其结果。 - 如果 Promise 对象 resolved,将结果存储到 `results` 数组中。 - 如果 Promise 对象 rejected,直接将整个 `Promise.all` 的 Promise 对象 rejected,并传递该错误给它。 6. 在所有 Promise 对象都处理完毕后,如果没有任何错误,则将 `results` 数组作为参数解析传递给 `Promise.all` 的 Promise 对象,并使其 resolved。 以下是一个示例代码,展示了如何手写实现 `Promise.all` 方法: ```javascript function myPromiseAll(promises) { return new Promise((resolve, reject) => { const results = []; const promisesCount = promises.length; let resolvedCount = 0; if (promisesCount === 0) { resolve(results); return; } function handleResolve(index, value) { results[index] = value; resolvedCount++; if (resolvedCount === promisesCount) { resolve(results); } } function handleReject(error) { reject(error); } for (let i = 0; i < promisesCount; i++) { Promise.resolve(promises[i]) .then((value) => handleResolve(i, value)) .catch(handleReject); } }); } // 示例 Promise 对象 const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); const promise3 = new Promise((resolve) => setTimeout(resolve, 1000, 3)); // 使用自定义的 Promise.all 方法 myPromiseAll([promise1, promise2, promise3]) .then((results) => { console.log(results); // 输出: [1, 2, 3] }) .catch((error) => { console.log(error); }); ``` 通过以上代码,你可以手动实现 JavaScript 中的 `Promise.all` 方法。请注意,这只是一个简单的示例,并没有处理所有可能的情况,如传入的参数不是一个数组等。在实际使用中,建议使用 JavaScript 原生的 `Promise.all` 方法来处理多个 Promise 对象的并行操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值