一、Promise对象简介
Promise是一个在ES6语法中引进的专门用于处理异步操作的对。
Promise代表的含义是异步操作的结果,即一个在现在、未来或永远不可用的值,通过Promise可以判断异步操作的顺利完成或失败。
在异步编程场景中,一般将Promise对象作为函数的返回结果,我们可以将Promise对象与回调函数进行绑定,将回调函数传给Promise对象。比起在指定的函数中调用回调函数,Promise对象提供了更加灵活的异步编程方法。
Promise对象在代码运行期间主要呈现三种状态:
Pending:任务处于初始状态。
Fulfilled:任务执行成功,结果可用。
Rejected:任务执行失败,并显示错误原因。
Promise对象的大致语法如下:
let promise_obj = new Promise((resolve, reject) => {
// 执行异步操作
if (isSuccessful) {
resolve("operation successful");
// 切换到fulfilled状态
} else {
reject("operation failed");
// 切换到rejected状态
}
});
代码样例:判断一个数是否为偶数
let checkEven = new Promise((resolve, reject) => {
let number = 6;
if (number % 2 === 0) {
resolve("The number is even!");
}
else {
reject("The number is odd!");
}
});
checkEven
.then((message) => console.log(message)) // On success
.catch((error) => console.error(error)); // On failure
运行结果:
The number is even!
二、创建Promise对象的方法
创建Promise对象时,需要将executor函数传递给Promise构造函数,该构造函数包含异步操作,并定义了异步操作执行成功和执行失败时对应的动作。
resolve和reject是构造Promise对象时默认要传入的两个参数。
Promise构造函数的语法:
let promise = new Promise(executor_function(resolve, reject) {
// async operation code
});
Promise构造函数的匿名函数写法:
let promise = new Promise((resolve, reject) => {
// async operation code
});
三、Promise对象的状态切换

Promise对象的状态切换遵循严格的生命周期规则,pending是初始状态,表示异步操作尚未完成。当异步操作执行成功时,状态变为fulfilled,此时会调用resolve函数,并且Promise.then()方法中的成功回调会被触发。当异步操作执行失败时,状态变为rejected,此时会调用reject函数,Promise.then()或Promise.catch()中的错误处理回调会被触发。
1.初始状态
构造Promise对象时的状态,此时状态为pending,既不成功也不失败。
对应Node.Js代码:
const promise = new Promise((resolve, reject) => {});

2.执行成功
状态从pending切换到fulfilled,通过resolve触发。
对应Node.Js代码:
const successPromise = new Promise((resolve) => {
setTimeout(() => resolve('success'), 1000);
//1秒后状态变为fulfilled
});

3.执行失败
状态从pending切换到rejected,通过reject或异常抛出来触发。
对应Node.Js代码:
const failPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("Failed")), 1000);
//1秒后状态变为rejected
});
const errorPromise = new Promise(() => {
throw new Error("Exception occured.");
//状态立即变为rejected
});
4.状态切换对应的函数触发
successPromise.then(value => {
console.log(value);
//在fulfilled状态触发
});
failPromise.catch(error => {
console.error(error);
//在rejected状态触发
});
// ES2018标准引入
errorPromise.finally(() => {
console.log('状态已确定');
//无论成功失败都会触发
});
5.状态转换规则
每个Promise对象只能进行一次状态切换。
切换后的状态将会被永久保持(settled)。
发生的每一个rejected都要有对应的处理,未被处理的rejected状态会导致UnhandledPromiseRejectionWarning异常。
只有等异步操作完成后才会开始触发状态的变更。
四、Promise对象的常用函数接口

1.Promise.then()函数
用于链式处理异步操作的结果,处理Promise的fullfiled或reject状态。
函数语法:
Promise.then(onFulfilled, onRejected)
代码样例:
const promise = new Promise((resolve) => resolve("success !"));
promise.then(
(value) => console.log(value),
(error) => console.error(error)
);
运行结果:
success !
2.Promise.catch()函数
专门用于处理Promise的reject状态。
函数语法:
Promise.catch(onRejected)
代码样例:
const promise1 = new Promise((resolve, reject) => {
reject("Failed !");
});
promise1.catch((error) => {
console.error(error);
});
运行结果:
Failed !
3.Promise.finally()函数
经常在清理资源时使用。
无论Promise成功或失败都会执行的函数。
函数语法:
Promise.finally(onFinally)
代码样例:
const p1 = Promise.resolve("Success.");
p1.then((result) => console.log(result))
.catch((error) => console.error(error))
.finally(() => console.log("Cleanup completed"));
运行结果:
Success.
Cleanup completed
4.Promise.all()函数
需要并行运行多个Promise并等待所有Promise执行完成时使用。
将可迭代的Promise数组作为输入,并返回单个Promise对象。
当所有Promise都执行成功时,返回fullfiled状态的Promise,如果有任何一个Promise执行失败,则返回reject状态的Promise。
函数语法:
Promise.all(iterable)
代码样例:
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
运行结果:
[ 3, 42, 'foo' ]
5.Promise.allSettled()函数
适合需要知道所有异步操作最终状态的场景,它可以等待所有Promise都完成,无论成功或失败。
将可迭代的Promise数组作为输入,并返回单个Promise对象。
当所有Promise都settle时,返回Promise结果。
函数语法:
Promise.allSettled(iterable)
代码样例:
const p1 = Promise.resolve(1);
const p2 = Promise.reject("Failed.");
Promise.allSettled([p1, p2]).then((results) => {
console.log(results);
});
运行结果:
[
{ status: 'fulfilled', value: 1 },
{ status: 'rejected', reason: 'Failed.' }
]
6.Promise.race()函数
常用于请求的超时处理。
将可迭代的Promise数组作为输入,并返回单个Promise对象。
返回的Promise结果与第一个settle的Promise结果一致。
函数语法:
Promise.race(iterable)
代码样例:
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "two");
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
});
运行结果:
two
五、Promise的异步编程实践
Demo1:链式调用
function asyncTask1() {
return new Promise(resolve => {
setTimeout(() => resolve(100), 1000);
});
}
asyncTask1()
.then(result => {
console.log(result);
return result * 2;
})
.then(newResult => {
console.log(newResult);
});
运行结果:
100
200
Demo2:配合fetch()使用
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(data => console.log(data));
fetch('https://jsonplaceholder.typicode.com/todos/2')
.then(response => response.json())
.then(data => console.log(data));
运行结果:
{
userId: 1,
id: 2,
title: 'quis ut nam facilis et officia qui',
completed: false
}
{ userId: 1, id: 1, title: 'delectus aut autem', completed: false }
Demo3:Web网页的动态交互
<script>
function askForName() {
const name = window.prompt('What is your name?');
const elem = document.querySelector('#greeting');
elem.innerText = `Hi ${name}!`
}
</script>
<button onclick="askForName()">
Click me
</button>
<div id="greeting"></div>
运行结果:


Demo4:模拟异步的数据加载
<!DOCTYPE html>
<html>
<head>
<title>Promise交互示例</title>
<style>
.container {
padding: 20px;
text-align: center;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
.loader {
display: none;
margin: 20px;
}
#result {
margin-top: 20px;
padding: 15px;
border: 1px solid #ddd;
min-height: 50px;
}
</style>
</head>
<body>
<div class="container">
<button id="loadBtn">加载数据</button>
<div class="loader">加载中...</div>
<div id="result"></div>
</div>
<script>
document.getElementById('loadBtn').addEventListener('click', () => {
const loader = document.querySelector('.loader');
const resultDiv = document.getElementById('result');
// 显示加载状态
loader.style.display = 'block';
resultDiv.innerHTML = '';
// 创建Promise进行异步操作
new Promise((resolve, reject) => {
// 模拟API请求
setTimeout(() => {
const success = Math.random() > 0.2; // 80%成功率
success ? resolve({ data: '成功获取的数据!' }) : reject('服务器错误');
}, 1500);
})
.then(response => {
resultDiv.innerHTML = response.data;
resultDiv.style.color = 'green';
})
.catch(error => {
resultDiv.innerHTML = `错误:${error}`;
resultDiv.style.color = 'red';
})
.finally(() => {
loader.style.display = 'none';
});
});
</script>
</body>
</html>
运行结果:


参考阅读:
https://javascript.info/Promise-basics
https://www.geeksforgeeks.org/javascript-Promise/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
703

被折叠的 条评论
为什么被折叠?



