likes
comments
collection
share

❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

作者站长头像
站长
· 阅读数 22

❤️ ❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

1、Promise简介

基本使用先看一眼

new Promise(( resolve, reject ) =>{})

(1)认识

含义

先看看这个Promise单词的含义:翻译成中文是许诺,非常好的名字,我们看看具体用来做什么

诞生目的

promise是为了解决 JavaScript 异步编程中的问题,旧的的ajax发单个请求还好,如果多请求不断嵌套和复用,将十分混乱,promise主要是为了解决这种情景而出现的,他提供了一种更优雅和可靠的方式来处理异步操作。

实用场景

举个例子(现在我们需要通过一个接口请求id ,再根据id请求用户名.再根据用户名,再根据用户名获取手机号),这个时候就用到这个promise

(2)发展历程

Promise 最早由社区提出,并被添加到 ECMAScript 6(ES6)标准中,

随着时间推移,Promise 在后续的 ECMAScript 标准中也增加了更多与 Promise 相关的特性,async/await 等,进一步简化了异步代码的编写。

(3)特点

  • 状态管理:三种状态,【pending(等待)、fulfilled(已成功)、rejected(已失败)】 ,可以清晰地知道异步操作的状态并进行后续操作。
  • 链式调用:可以轻松地串联多个异步操作,避免回调地狱问题。
  • 错误处理:提供了统一的错误处理机制,通过 catch 方法可以捕获链中任意位置抛出的错误。

(4)优点

让传统的多ajax请求更优雅

(5)缺点

  • 许诺,意思就是一旦许诺完毕,就无法更改! 所以,一个Promise一旦新建它就会立即执行,无法中途取消。

  • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部,我们也压根得不到,不知道发生了什么。

-当处于Pending状态时,无法得知目前狀態(不知道是刚刚开始还是即将完成)。

如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise更好的选择。

(6)Promise 构造函数

首先你得清楚,他就是函数,那他是用来做什么的呢。

来创建 Promise 对象的函数。通过调用 new Promise(executor) 来创建一个新的 Promise 实例,其中 executor 是一个带有 resolvereject 两个参数的函数:

const myPromise = new Promise((resolve, reject) => {
  // 异步操作代码
  if (/* 操作成功 */) {
    resolve('成功的结果');
  } else {
    reject('失败的原因');
  }
});

❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

如图所示,其实这个就是传入的那个函数executor

也就是在 Promise 构造函数中,接受一个执行器函数,该函数立即执行,并包含异步操作的逻辑,通过 resolve 或 reject 来改变 Promise 的状态。

(7)Promise 实例

通过 Promise 构造函数创建的对象,代表一个异步操作的最终结果(成功或失败)

可以调用 .then().catch() 和 .finally() 方法来处理异步操作的结果。

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('操作成功'); // 模拟异步操作成功
  }, 1000);
});

myPromise.then(result => {
  console.log(result); // 输出 "操作成功"
}).catch(error => {
  console.error(error);
});

(8)解决痛点

这里我们可以简单看一下没有promise的时候是怎么使用的

我们先以一个简单的网络请求为示例:

// 请求A 函数
(function A(resultA){
    // 处理resultA
    ...
    resultA;
})

两个或者多个呢

// 请求A 函数
(function A(resultA){
    // 处理resultA
    ...
    function B(resultB){
    	// 处理 resultB
    	...
    	function C(resultC){
	    	// 处理 resultC
	    	...
		}
	}
})

来看看六层结构的时候是什么样子

// 六层嵌套结构
// 请求A 函数
(function A(resultA){
    console.log('处理 resultA:', resultA);   // 处理resultA
    function B(resultB){
        console.log('处理 resultB:', resultB);// 处理 resultB
        function C(resultC){
            console.log('处理 resultC:', resultC); // 处理 resultC
            function D(resultD){
                console.log('处理 resultD:', resultD); // 处理 resultD
                function E(resultE){
                    console.log('处理 resultE:', resultE);  // 处理 resultE
                    function F(resultF){
                        console.log('处理 resultF:', resultF); // 处理 resultF
                    }
                    // 调用函数F
                    const resultF = '结果F';
                    F(resultF);
                }
                const resultE = '结果E';  // 调用函数E
                E(resultE);
            }
            const resultD = '结果D'; // 调用函数D
            D(resultD);
        }
        const resultC = '结果C'; // 调用函数C
        C(resultC);
    }
    const resultB = '结果B'; // 调用函数B
    B(resultB);
})('结果A');

难以维护,有时候我们还要在里面添加更多的逻辑和操作

但是我们使用更加友好的代码组织方式,把异步写成同步的方式是不是更好一些呢?

// 调用函数A并获取结果
let resultA = A();

// 调用函数B并获取结果,传入resultA
let resultB = B(resultA);

// 调用函数C并获取结果,传入resultB
let resultC = C(resultB);

// 调用函数D并获取结果,传入resultC
let resultD = D(resultC);

// 调用函数E并获取结果,传入resultD
let resultE = E(resultD);

// 调用函数F,传入resultE
F(resultE);

应用到正式的写法之中就可以缩减为

// Define request functions (assuming they return Promises)
function request1() {
    return new Promise((resolve, reject) => {
        // Async operation, simulate request 1
        setTimeout(() => {
            console.log('Request 1 completed');
            resolve('Result 1'); // Simulate successful request 1 with result 1
        }, 1000);
    });
}

function request2(result1) {
    return new Promise((resolve, reject) => {
        // Async operation, simulate request 2 using result 1
        setTimeout(() => {
            console.log('Request 2 completed, using:', result1);
            resolve('Result 2'); // Simulate successful request 2 with result 2
        }, 1000);
    });
}

function request3(result2) {
    return new Promise((resolve, reject) => {
        // Async operation, simulate request 3 using result 2
        setTimeout(() => {
            console.log('Request 3 completed, using:', result2);
            resolve('Result 3'); // Simulate successful request 3 with result 3
        }, 1000);
    });
}

function request4(result3) {
    return new Promise((resolve, reject) => {
        // Async operation, simulate request 4 using result 3
        setTimeout(() => {
            console.log('Request 4 completed, using:', result3);
            resolve('Result 4'); // Simulate successful request 4 with result 4
        }, 1000);
    });
}

function request5(result4) {
    return new Promise((resolve, reject) => {
        // Async operation, simulate request 5 using result 4
        setTimeout(() => {
            console.log('Request 5 completed, using:', result4);
            resolve('Result 5'); // Simulate successful request 5 with result 5
        }, 1000);
    });
}

// Define function to handle exceptions
function handleException(error) {
    console.error('Exception occurred:', error);
}

// Using Promise chaining
new Promise(request1)
    .then(result1 => request2(result1))
    .then(result2 => request3(result2))
    .then(result3 => request4(result3))
    .then(result4 => request5(result4))
    .then(result5 => {
        console.log('All requests completed, final result:', result5);
    })
    .catch(error => handleException(error));

这个时候就诞生了最著名的 Q 和 bluebird等库。

2、Promise状态

一个 Promise 对象有三种状态:

  1. Pending(等待):初始状态,既不成功,也不失败。
  2. Fulfilled(已成功 又称为Resolved):操作成功
  3. Rejected(已失败):操作失败

写一个普通的Promise来看一下我们对应的状态

首先是成功和完成!


 const myPromise = new Promise((resolve, reject) => {
    const success = true; // 模拟异步操作的结果

    if (success) {
        resolve('myPromise 操作成功!'); // 操作成功时调用 resolve
    } else {
        reject('myPromise 操作失败!'); // 操作失败时调用 reject
    }
});

myPromise
    .then(value => {
        console.log(value); // 操作成功时执行
    })
    .catch(error => {
        console.error(error); // 操作失败时执行
    })
    .finally(() => {
        console.log('myPromise has completed.'); // 无论成功或失败都会执行
    });

操作成功以后返回给我们!

❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

操作失败:(把success换成false)

❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

3、promise.实例对象方法

先看一下我们使用上述的方法

myPromise
      .then(value => {
        console.log(value); // 操作成功时执行
      })
      .catch(error => {
        console.error(error); // 操作失败时执行
      })
      .finally(() => {
        console.log('Operation has completed.'); // 无论成功或失败都会执行
      });

(1) .then

用户 Promise 成功时要执行的回调函数。它还可以接受一个可选的第二个参数,用于处理 Promise 被拒绝的情况

就类似我们登录请求不成功会给用户提示或者去登录页登录一样

myPromise.then(onFulfilled, onRejected);
  • onFulfilled:当 Promise 成功时要执行的回调函数。
  • onRejected:当 Promise 被拒绝时要执行的回调函数(可选)

(2) .catch

catch 方法用于定义当 Promise 被拒绝时要执行的回调函数。它相当于 then 方法的第二个参数。

通常我们会在这里区捕获一些接口异常信息等!

myPromise.catch(onRejected);

(3) .finally

ES9(2018)新实例方法

finallyPromise 结束时(无论成功还是失败)执行,也就是最后肯定会执行这个,有时候我们就会拿来查询之前改的列表状态

myPromise.finally(onFinally);

4、Promise静态方法

(1) Promise.resolve(静态方法)

Promise.resolve 方法返回一个以给定值解析后的 Promise

如果该值是一个 Promise,那么直接返回这个 Promise

const resolvedPromise = Promise.resolve(42);
resolvedPromise.then(value => {
      console.log(value); // 42
});

(2) Promise.reject 方法(静态方法)

Promise.reject 返回一个状态为 rejected 的 Promise 对象,并且可以指定拒绝的原因(通常是一个错误对象)。

我们可以在异步操作时候立马拒绝 Promise时候使用,比如(某些条件不满足或者发生错误时)

const rejectedPromise = Promise.reject(new Error('Something went wrong')); 

rejectedPromise.catch(error => { 
    console.error(error); // Error: Something went wrong 
   });

(3) Promise.all

接受一个 Promise 的迭代器,并返回一个新的 Promise,该 Promise 在所有传入的 Promise 都完成时完成,并带有一个数组的成功结果。

如果任意一个传入的 Promise 失败,那么返回的 Promise 将立即失败,并带有第一个失败的 Promise 的错误原因。

举个例子,必须查询出三种类别(由三个接口提供),再依靠我们查出来的类别进行选择时我们可以采用。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'foo'));
const promise3 = 42;

Promise.all([promise1, promise2, promise3]).then(values => {
  console.log(values); // [3, "foo", 42]
});

当我们把其中定时器加上三秒的时候,也是之后给我们一起返回

❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

(4)Promise.race

翻译成中文就是竞争竞赛,就是有个人赢了那就是结束了

接受一个 Promise 的迭代器,并返回一个新的 Promise,该 Promise 在传入的任意一个 Promise 完成时立即完成,带有这个 Promise 的成功结果或错误原因。

就是类似于 或 的关系,A||B 有任意一个成立就可以!

const promise1 = new Promise((resolve, reject) => setTimeout(resolve, 5000, 'one'));

const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 10000, 'two'));

Promise.race([promise1, promise2]).then(value => {
      console.log(value); // "two"
});

5、promise 对象实例和Promise静态方法区分

这里可能对于promise上的对象实例和静态方法不清楚,我们,我们看一下两者之间的区别

Promise.rejectpromise.then 来区分

不同点

  1. 调用方式
  • Promise.reject 是一个静态方法,直接通过 Promise 构造函数调用,不需要先创建 Promise 实例。
  • promise.then 是 Promise 实例的方法,必须在已有 Promise 实例上调用。
  1. 作用
  • Promise.reject 用于创建一个立即被拒绝的 Promise 对象,通常用于快速返回失败状态的场景。
  • promise.then 用于设置成功和失败时的回调函数,允许进行链式操作。

相同点

  • 都可以用来处理Promise 的状态变化异步操作的结果。
  • 都支持链式调用,可连续地对异步操作进行处理。

这里我们简单写一下使用区分一下:

// 1  使用 Promise.reject
const rejectedPromise = Promise.reject(new Error('Reason for rejection'));
rejectedPromise.catch(error => {
  console.error(error.message); // Output: "Reason for rejection"
});




// 2   使用 promise.then
const myPromise = new Promise((resolve, reject) => {
  const success = false; // 模拟一个失败的异步操作
  if (success) {
    resolve('Operation was successful!');
  } else {
    reject(new Error('Operation failed!'));
  }
});

myPromise.then(
  result => {
    console.log(result); // 操作成功时执行
  },
  error => {
    console.error(error.message); // 操作失败时执行
  }
);

6、Promise链式调用

链式调用可以轻松处理一系列的异步操作并优化和简化我们的代码

new Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000); // 1秒后变为resolved状态
})
.then(result => {
  console.log(result); // 1
  return result * 2;
})
.then(result => {
  console.log(result); // 2
  return result * 2;
})
.then(result => {
  console.log(result); // 4
  return result * 2;
});

打印出可以看到 ❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

(1) 链式错误

Promise 链中,如果某个 then 或者 catch 抛出了错误,后续的 catch 将会捕获到这个错误

我们在链式之中抛出一个异常试试  

new Promise((resolve, reject) => {
  throw new Error("Whoops!");
})
.catch(error => {
  console.error(error); // Error: Whoops!
  return "Recovered";
})
.then(result => {
  console.log(result); // Recovered
});

❤Promise(then,catch,finally,all,race,allsettled,any)-三千字总结

7、手写一个 Promise过程

转载自:https://juejin.cn/post/7382868373882880000
评论
请登录