👻认识promise作用

👻promise介绍

在 JavaScript 中,Promise 是一种强大的异步编程工具,它的作用在于处理异步操作,使得代码更>具可读性和可维护性。Promise 最早出现在 ECMAScript 6(ES6)中,它为开发者提供了一种更结>构化的方式来处理异步任务,尤其是网络请求、文件读写、定时任务等等。

👻Promise 主要作用

  1. 处理异步操作:Promise 可以用来处理异步操作,例如网络请求、文件读写、定时器等等。这有助于避免回调地狱(Callback Hell)和提高代码的可读性。
  2. 更好的错误处理:Promise 允许我们轻松地捕获和处理异步操作中的错误,而不需要使用传统的 try-catch 块。
  3. 链式调用:Promise 支持链式调用,可以按顺序执行一系列的异步操作,使代码看起来更加清晰。

👻promise基本使用

Promise 是一个代表异步操作最终完成或失败的对象。一个 Promise 可以处于以下三种状态之一:

  1. Pending(进行中):初始状态,表示异步操作还在进行中,尚未完成或失败。
  2. Fulfilled(已完成):表示异步操作已成功完成。
  3. Rejected(已失败):表示异步操作发生了错误或失败。

下面是一个基本的 Promise 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const myPromise = new Promise((resolve, reject) => {
// 异步操作,例如发送网络请求
setTimeout(() => {
const randomNumber = Math.random();
if (randomNumber < 0.5) {
resolve("成功:数据加载完成");
} else {
reject("失败:数据加载失败");
}
}, 1000);
});

myPromise.then((result) => {
console.log(result); // 成功:数据加载完成
}).catch((error) => {
console.error(error); // 失败:数据加载失败
});

在这个示例中,创建了一个 Promise 对象 myPromise,它模拟了一个异步操作。当异步操作完成时,调用 resolve 函数表示成功,调用 reject 函数表示失败。然后,使用 .then() 方法来处理成功的情况,使用 .catch() 方法来处理失败的情况。

👻promise的状态及状态变化

Promise 的三种状态:Pending(进行中)、Fulfilled(已成功)和Rejected(已失败)。这些状态是不可逆转的,一旦 Promise 进入了 Fulfilled 或 Rejected 状态,它将永远保持在这个状态,并且无法再次改变。

👻1. Pending(进行中)

Promise 最初的状态是 Pending,表示异步操作正在进行中,但尚未完成。在这个状态下,Promise 可以转换为 Fulfilled 或 Rejected 状态,取决于异步操作的结果。

👻2. Fulfilled(已成功)

当异步操作成功完成时,Promise 的状态将从 Pending 转换为 Fulfilled。这表示异步操作已成功,并且可以获取到结果值。

👻3. Rejected(已失败)

当异步操作由于某种原因失败时,Promise 的状态将从 Pending 转换为 Rejected。这表示异步操作已失败,并且可以获取到错误信息。

👻状态变化示例

下面是一个示例,演示了 Promise 的状态变化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const successPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功结果");
}, 1000);
});

const failurePromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("失败原因"));
}, 1000);
});

successPromise
.then((result) =>
console.log("成功状态:", result);
})
.catch((error) => {
console.error("失败状态:", error.message);
});

failurePromise
.then((result) => {
console.log("成功状态:", result);
})
.catch((error) => {
console.error("失败状态:", error.message);
});

在上面的示例中,successPromise 成功完成,进入 Fulfilled 状态,并输出成功状态的结果。而 failurePromise 由于出错而进入 Rejected 状态,并输出失败状态的错误信息。

👻promise实例方法

Promise 提供了一系列实例方法,用于处理异步操作和状态变化。

👻1. then 方法

then 方法是 Promise 中最重要的方法之一,用于注册回调函数来处理异步操作的结果。它接受两个参数:onFulfilledonRejected,分别用于处理成功和失败的情况。

👻基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const myPromise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
resolve("数据加载完成"); // 成功时调用 resolve
// 或者
// reject(new Error("数据加载失败")); // 失败时调用 reject
}, 1000);
});

myPromise
.then((result) => {
console.log(result); // 成功:数据加载完成
})
.catch((error) => {
console.error(error.message); // 失败:数据加载失败
});

👻多次调用 then

同一个 Promise 实例可以调用多次 then 方法,当 Promise 中的 resolve 被回调时,所有 then 方法传入的回调函数都会被调用。

1
2
3
4
5
6
7
8
9
const promise = new Promise((resolve) => {
resolve("你好");
});

// 同时调用多个 then 方法
promise.then((res) => console.log(res));
promise.then((res) => console.log(res));
promise.then((res) => console.log(res));

👻then 方法回调函数的返回值

then 方法传入的回调函数可以有返回值。如果返回的是普通值,那么这个普通值将作为一个新的 Promise 的 resolve 的值。

1
2
3
4
5
6
const promise = new Promise((resolve) => {
resolve("你好");
});

promise.then(() => "then").then((res) => console.log(res)); // 打印 "then"

如果返回的是 Promise,那么就可以再次调用 then 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const promise = new Promise((resolve) => {
resolve("你好");
});

promise
.then(() => {
return new Promise((resolve) => {
setTimeout(() => {
resolve("success");
}, 2000);
});
})
.then((msg) => {
// 2 秒后打印 "success"
console.log(msg);
});

如果返回的是一个对象,并且该对象实现了 thenable,该 then 函数有两个参数 resolvereject,则 resolve 的值将会传递给下一个 Promise。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const promise = new Promise((resolve) => {
resolve("你好");
});

promise
.then(() => {
return {
then(resolve) {
return resolve("success");
},
};
})
.then((msg) => {
// 打印 "success"
console.log(msg);
});

👻2. catch 方法

除了通过 then 方法的第二个参数来捕获 reject 错误之外,还可以使用 catch 方法,它返回一个新的 Promise,用于处理 Promise 实例的错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const promise = new Promise((resolve, reject) => {
reject("error");
});

// 使用 catch 捕获错误
promise.catch((err) => {
console.error(err); // 打印 "error"
});

// 或者
promise
.then(() => {})
.catch((err) => {
console.error(err); // 打印 "error"
});

catch 方法也可以多次调用,只要 Promise 实例的状态为 rejected,那么就会调用 catch 方法。

1
2
3
4
5
6
7
8
9
10
11
12
const promise = new Promise((resolve, reject) => {
reject("error");
});

// 这两个 catch 都会调用
promise.catch((err) => {
console.log(err);
});
promise.catch((err) => {
console.log(err);
});

👻3. finally 方法

finally 方法是 ES9(ES2018) 新增的特性,无论一个 Promise 实例是 fulfilled 还是 rejectedfinally 都会执行。它不接收任何参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const promise = new Promise((resolve, reject) => {
reject("error");
});

promise
.then((res) => {
console.log("res:", res);
})
.catch((err) => {
console.log("err", err);
})
.finally(() => {
console.log("finally code execute");
});

finally 方法适用于需要在不管 Promise 状态如何都要执行一些清理操作的场景。

👻promise的类方法

除了 Promise 实例方法,Promise 还提供了一些类方法,用于创建和处理多个 Promise 实例。

👻1. Promise.resolve()

Promise.resolve() 方法返回一个以给定值解析后的 Promise 对象。如果该值是一个 Promise,它将被返回原封不动(不进行解析)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const resolvedPromise = Promise.resolve("解析成功");
const rejectedPromise = Promise.reject("解析失败");

resolvedPromise.then((result) => {
console.log(result); // 解析成功
});

rejectedPromise.catch((error) => {
console.error(error); // 解析失败
});

// 处理 Promise 实例
const originalPromise = new Promise((resolve) => {
resolve("原始 Promise");
});

const resolvedWithPromise = Promise.resolve(originalPromise);

resolvedWithPromise.then((result) => {
console.log(result); // 原始 Promise
});

👻2. Promise.reject()

Promise.reject() 方法返回一个带有拒绝原因的 Promise 对象。

1
2
3
4
5
6
const rejectedPromise = Promise.reject("拒绝原因");

rejectedPromise.catch((error) => {
console.error(error); // 拒绝原因
});

👻3. Promise.all()

Promise.all() 方法接受一个可迭代的对象,如数组或字符串,里面包含多个 Promise 对象,并返回一个新的 Promise 对象。这个新的 Promise 在所有输入的 Promise 都成功解析后才会解析,如果任何一个 Promise 被拒绝,它就会立即被拒绝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const promise1 = Promise.resolve("第一个 Promise");
const promise2 = Promise.resolve("第二个 Promise");
const promise3 = Promise.reject("第三个 Promise");

Promise.all([promise1, promise2])
.then((results) => {
console.log(results); // ["第一个 Promise", "第二个 Promise"]
})
.catch((error) => {
console.error(error);
});

Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // 这里不会执行,会立即被拒绝
})
.catch((error) => {
console.error(error); // 第三个 Promise 拒绝的原因
});

👻4. Promise.race()

Promise.race() 方法接受一个可迭代的对象,如数组或字符串,里面包含多个 Promise 对象,并返回一个新的 Promise 对象。这个新的 Promise 在第一个输入的 Promise 成功解析或拒绝后立即解析或拒绝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve("第一个 Promise");
}, 1000);
});

const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve("第二个 Promise");
}, 500);
});

Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // 第二个 Promise(因为它解析得更快)
})
.catch((error) => {
console.error(error);
});

👻Promise 链的执行

在 JavaScript 中,Promise 链是一种处理多个异步操作的方法,其中一个操作的结果将传递给下一个操作。这种方法使得异步操作能够按照预期的顺序执行,提高了代码的可读性和可维护性。

👻创建 Promise 链

Promise 链是通过在 then 方法中返回新的 Promise 来创建的。每次调用 then 方法都会返回一个新的 Promise,它可以用来定义下一个操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const initialPromise = someAsyncOperation();

initialPromise
.then((result) => {
// 第一个异步操作的结果
return anotherAsyncOperation(result); // 返回新的 Promise
})
.then((result) => {
// 第二个异步操作的结果
return yetAnotherAsyncOperation(result); // 返回新的 Promise
})
.then((finalResult) => {
// 最终的结果
console.log("最终结果:", finalResult);
})
.catch((error) => {
// 处理任何错误
console.error("错误:", error);
});

在上面的示例中,initialPromise 是一个异步操作的 Promise。我们通过 then 方法创建了一个 Promise 链。在每个 then 中,我们可以访问前一个操作的结果,并返回一个新的 Promise 来定义下一个操作。最后,使用 catch 方法来处理任何可能的错误。

👻Promise 链的执行顺序

Promise 链中的操作是按照顺序执行的,每个操作都在前一个操作成功完成后才会触发。这确保了异步操作的顺序性。

如果某个操作返回一个普通的值而不是 Promise,它将被包装成一个立即成功的 Promise,并立即传递给下一个操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const promiseChain = Promise.resolve(1)
.then((result) => {
console.log("第一步:", result);
return result + 1; // 返回一个新的值
})
.then((result) => {
console.log("第二步:", result);
return result * 2; // 返回一个新的值
})
.then((result) => {
console.log("第三步:", result);
throw new Error("出错了"); // 抛出一个错误
})
.catch((error) => {
console.error("捕获到错误:", error.message);
});

// 输出:
// 第一步: 1
// 第二步: 2
// 第三步: 4
// 捕获到错误: 出错了

👻异步操作的顺序性

Promise 链的执行顺序确保了异步操作的顺序性,即使异步操作本身具有不同的执行时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

delay(1000)
.then(() => {
console.log("第一步完成");
return delay(2000); // 2 秒延迟
})
.then(() => {
console.log("第二步完成");
return delay(500); // 0.5 秒延迟
})
.then(() => {
console.log("第三步完成");
});

// 输出:
// 第一步完成
// 第二步完成
// 第三步完成

在上面的示例中,尽管每个 delay 函数具有不同的延迟时间,但它们仍然按照顺序执行。

👻Promise 链中的错误处理

如果任何一个异步操作失败(Promise 进入 Rejected 状态),错误会传递给最近.catch() 方法进行处理。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
asyncOperation1()
.then((result1) => {
console.log(result1); // 操作 1 完成
return asyncOperation2(); // 返回第二个异步操作的 Promise
})
.then((result2) => {
console.log(result2); // 操作 2 完成
throw new Error("操作 3 失败"); // 手动抛出错误
})
.then((result3) => {
console.log(result3); // 不会执行到这里
})
.catch((error) => {
console.error("出错了:", error); // 出错了: Error: 操作 3 失败
});

在上面的示例中,第二个 .then() 方法手动抛出了一个错误,因此会触发 .catch() 方法来处理错误。