Javascript 手写一个Promise

  难点图解:then()方法

a01d447934ca4ffda2be39503b3a53ed.png

ES6学习网站:ES6 入门教程

解决:回调地狱(回调函数中嵌套回调)

两个特点:

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

实现Promise

手写实现一个基本的 Promise 涉及到几个核心部分:状态管理(pending, fulfilled, rejected)、then 方法实现(支持链式调用)、catch 方法实现(错误处理)、以及 finally 方法的可选实现。下面是一个简化版的 Promise 实现:

function Promise(executor) {  
    if (typeof executor !== 'function') {  
        throw new TypeError('Promise resolver undefined is not a function');  
    }  
  
    // Promise 的三种状态  
    const PENDING = 'pending';  
    const FULFILLED = 'fulfilled';  
    const REJECTED = 'rejected';  
  
    let status = PENDING;  
    let value = undefined;  
    let reason = undefined;  
  
    // 存储成功和失败的回调  
    const onFulfilledCallbacks = [];  
    const onRejectedCallbacks = [];  
  
    function resolve(newValue) {  
        if (status === PENDING) {  
            // 新的值需要是Promise,则递归解析  
            if (newValue instanceof Promise) {  
                return newValue.then(resolve, reject);  
            }  
            status = FULFILLED;  
            value = newValue;  
            // 异步执行所有成功回调  
            onFulfilledCallbacks.forEach(fn => fn());  
        }  
    }  
  
    function reject(newReason) {  
        if (status === PENDING) {  
            status = REJECTED;  
            reason = newReason;  
            // 异步执行所有失败回调  
            onRejectedCallbacks.forEach(fn => fn());  
        }  
    }  
  
    // 捕获执行器抛出的错误  
    try {  
        executor(resolve, reject);  
    } catch (e) {  
        reject(e);  
    }  
  
    // then 方法  
    this.then = function(onFulfilled, onRejected) {  
        return new Promise((resolve, reject) => {  
            // 处理成功情况  
            function handleOnFulfilled() {  
                try {  
                    if (typeof onFulfilled === 'function') {  
                        const result = onFulfilled(value);  
                        // 如果结果是Promise,则继续等待,否则直接解析  
                        if (result instanceof Promise) {  
                            result.then(resolve, reject);  
                        } else {  
                            resolve(result);  
                        }  
                    } else {  
                        resolve(value);  
                    }  
                } catch (e) {  
                    reject(e);  
                }  
            }  
  
            // 处理失败情况  
            function handleOnRejected() {  
                try {  
                    if (typeof onRejected === 'function') {  
                        const result = onRejected(reason);  
                        if (result instanceof Promise) {  
                            result.then(resolve, reject);  
                        } else {  
                            resolve(result);  
                        }  
                    } else {  
                        reject(reason);  
                    }  
                } catch (e) {  
                    reject(e);  
                }  
            }  
  
            // 根据当前Promise的状态决定是执行成功回调还是失败回调  
            if (status === FULFILLED) {  
                setTimeout(handleOnFulfilled);  
            } else if (status === REJECTED) {  
                setTimeout(handleOnRejected);  
            } else {  
                // 如果状态还未确定,则添加到对应的回调数组中  
                onFulfilledCallbacks.push(handleOnFulfilled);  
                onRejectedCallbacks.push(handleOnRejected);  
            }  
        });  
    };  
  
    // catch 方法  
    this.catch = function(onRejected) {  
        return this.then(null, onRejected);  
    };  
  
    // finally 方法(可选实现)  
    this.finally = function(onFinally) {  
        return this.then(  
            value => Promise.resolve(onFinally()).then(() => value),  
            reason => Promise.resolve(onFinally()).then(() => { throw reason; })  
        );  
    };  
}  
  
// 示例用法  
new Promise((resolve, reject) => {  
    setTimeout(() => resolve('hello'), 1000);  
}).then(data => {  
    console.log(data); // 输出: hello  
    return 'world';  
}).then(data => {  
    console.log(data); // 输出: world  
}).catch(error => {  
    console.error(error);  
});

创建 Promise

你可以使用 new Promise() 构造函数来创建一个 Promise。它接受一个带有 resolvereject 两个参数的函数,这个函数会在异步操作完成(成功或失败)时被调用。

let myPromise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    let success = true;
    if (success) {
      resolve("操作成功!"); // 成功时调用 resolve,状态fulfill且改变当前promise对象的结果
    } else {
      reject("操作失败!"); // 失败时调用 reject
    }
  }, 2000); // 模拟2秒延迟
});

  Promise原型的方法

then()

p.then(value)=>{console.log('value')},成功调用时执行,resolve()类似声明,将形参传给then()方法

在then()方法的参数函数中,通过形参使用promise对象的结果

如果promise的状态不改变,then()里的方法不会执行

使用return会将当前promise实例的状态改成fulfilled,return返回值将作为形参传给下一个then()

如果当前then()中代码出错,会将promise实例的状态改成rejected
53b4f135c03e44deb2c486e89051026d.png

3ed262dd936c49878cb587cb1ea2499a.png

catch()

catch(),失败调用时执行

何时触发?reject()或者Promise执行体中有错

处理 Promise

使用 then() 方法来处理 Promise 对象的成功完成情况,并使用 catch() 方法来处理失败情况。

myPromise.then((message) => {
  console.log("成功:", message); // Promise 被 resolve 时执行
}).catch((error) => {
  console.error("错误:", error); // Promise 被 reject 时执行
});

 上边说到Promise是一个构造函数,new之后等于说调用了构造函数,构造函数中传的参数是一个函数,这个函数内的两个参数分别又是两个函数(reslovereject)

Promise 链 

Promise 可以通过链式调用进一步简化处理多个异步操作的代码。在 then() 方法中返回一个新的 Promise对象状态为pending,可以使得链式调用变得更加清晰。

// 假设有一个函数 fetchUserData 返回一个 Promise,用于获取用户数据
fetchUserData()
  .then((userData) => {
    // 处理获取到的用户数据
    return fetchUserPosts(userData.userId); // 返回另一个 Promise
  })
  .then((userPosts) => {
    // 处理获取到的用户发帖数据
  })
  .catch((error) => {
    console.error("处理过程中出现错误:", error);
  });

 Promise.all 

Promise.all() 用于同时处理多个 Promise,并在所有 Promise 都成功时返回一个包含所有结果的 Promise,但只要有一个 Promise 失败,它就会立即返回失败

let promise1 = someAsyncOperation();
let promise2 = anotherAsyncOperation();

Promise.all([promise1, promise2])
  .then((results) => {
    // results 包含了两个 Promise 的结果
  })
  .catch((error) => {
    // 处理失败情况
  });

Promise.race

 Promise.race() 用于竞争多个 Promise,返回一个新的 Promise,其结果由最先完成的 Promise 决定

let promise1 = fetchUserData();
let promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("操作超时!");
  }, 500); // 模拟超时操作
});

Promise.race([promise1, promise2])
  .then((result) => {
    // 处理最先完成的 Promise 的结果
  })
  .catch((error) => {
    // 处理失败情况,可能是超时或其他原因
  });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值