是什么
Promise 是 JavaScript 中用于处理异步操作的一种对象。它代表了一个尚未完成但承诺会在未来某个时候完成的操作,并允许你在操作完成前注册回调函数。
-
三种状态
- Pending 等待
- Fulfilled 完成
- Rejected 失败
-
两个过程
状态只能由 Pending --> Fulfilled 或者 Pending --> Rejected,且一但发生改变便不可二次修改
-
三个方法
then:注册fulfilled状态回调函数
catch:注册rejected状态回调函数
finally:注册无论成功或失败都会执行的回调函数
属于微任务 是异步任务的一种
Promise.prototype 原型上的方法
Promise.prototype.then
-
.then()
方法用于指定当Promise
对象的状态变为fulfilled
时要执行的回调函数。 -
它接受两个可选的回调函数作为参数:第一个用于处理成功的情况,第二个(可选的)用于处理错误(但通常不会在这里处理错误,而是使用
.catch()
)。
* 该方法返回结果是一个新的Promise实例,可以继续调用then方法
Promise.prototype.catch
.catch()
方法用于指定当Promise
对象的状态变为rejected
(即异步操作失败)时要执行的回调函数。- 它只接受一个回调函数作为参数,该回调函数会接收被
reject
方法传递的错误信息。
javascript
getJSON('/posts.json')
.then(function(posts) {
// ...
})
.catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
上面代码中,getJSON()
方法返回一个 Promise 对象,如果该对象状态变为resolved
,则会调用then()
方法指定的回调函数;
如果异步操作抛出错误,状态就会变为rejected
,就会调用catch()
方法指定的回调函数,处理这个错误。
另外,then()
方法指定的回调函数,如果运行中抛出错误,也会被catch()
方法捕获。
Promise.prototype.finally()
finally()
方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
Promise 类上方法
处理多个异步操作
Promise.all()
Promise.all()
接收promise对象数组,返回一个新的promise对象,当数组中所有promise都解决时成功时,返回的promise对象才会解决
javascript
const p = Promise.all([p1, p2, p3]);
- 上面代码中,
Promise.all()
方法接受一个数组作为参数,p1
、p2
、p3
都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理。
p
的状态由p1
、p2
、p3
决定,分成两种情况。
-
只有
p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数。 -
只要
p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。
Promise.allSettled()
接收一个 promise 对象数组,并返回一个新的 promise。无论数组中的 promise 是解决还是拒绝,返回的 promise 都会解决
有时候,我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。
例如获取多个用户的信息,当有几个用户信息成功获取到进行处理
Promise.all()
方法只适合所有异步操作都成功的情况,如果有一个操作失败,就无法满足要求。
javascript
// Promise.all 示例
const promise1 = Promise.resolve(3);
const promise2 = Promise.resolve(42);
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(values => {
console.log(values); // [3, 42, "foo"]
}).catch(error => {
console.error('Error:', error);
});
Promise.all 更适用于处理所有 promise 都需要成功的情况,
而 Promise.allSettled 更适用于需要知道每个 promise 结果的情况。
javascript
const promise4 = Promise.resolve(3);
const promise5 = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'error');
});
const promise6 = Promise.resolve(42);
Promise.allSettled([promise4, promise5, promise6]).then(results => {
results.forEach(result => console.log(result.status));
// fulfilled
// rejected
// fulfilled
});
Promise.race()
Promise.race()
接收promise对象数组,返回一个新的promise对象,当数组中有一个promise解决时无论成功还是失败,返回的promise对象就会解决
javascript
const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1
、p2
、p3
之中有一个实例率先改变状态,p
的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p
的回调函数。
Promise.race()
方法的参数与Promise.all()
方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve()
方法,将参数转为 Promise 实例,再进一步处理。
Promise.any()
接收promise数组,返回一个新的 Promise
javascript
Promise.any([
fetch('https://v8.dev/').then(() => 'home'),
fetch('https://v8.dev/blog').then(() => 'blog'),
fetch('https://v8.dev/docs').then(() => 'docs')
]).then((first) => { // 只要有一个 fetch() 请求成功
console.log(first);
}).catch((error) => { // 所有三个 fetch() 全部请求失败
console.log(error);
});
- 只要参数实例有一个变成
fulfilled
状态,包装实例就会变成fulfilled
状态; - 如果所有参数实例都变成
rejected
状态,包装实例就会变成rejected
状态。
Promise.any()
跟Promise.race()
方法很像,只有一点不同,就是Promise.any()
不会因为某个 Promise 变成rejected
状态而结束,必须等到所有参数 Promise 变成rejected
状态才会结束。
创建promise对象
Promise.resolve()
Promise.resolve()
方法一般情况下返回一个状态为已解决的 Promise
对象。
参数可以是:
- 一个 Promise 对象:直接返回该 Promise 对象。
- 一个 thenable 对象 (即具有
then
方法的对象):将其视为 Promise 对象并返回一个新的 Promise,该 Promise 会采用该 thenable 对象的最终状态。 - 非 Promise/thenable 值:返回一个新的已解决的 Promise 对象,其解决值为该参数值。
Promise.reject()
Promise.reject()
方法返回一个状态为已拒绝的 Promise
对象。
参数是拒绝理由,可以是任何类型的值(通常是一个 Error
对象或字符串)。
为什么
- 在js中实现异步操作
- 可以链式调用,解决回调地狱的问题
回调地狱
js
fs.readFile('file1.txt', function(err, data1) {
if (err) throw err;
fs.readFile('file2.txt', function(err, data2) {
if (err) throw err;
fs.readFile('file3.txt', function(err, data3) {
if (err) throw err;
// 继续嵌套下去...
});
});
});
Promise 的链式调用可以让我们避免回调地狱。每个 .then
方法都会返回一个新的 Promise,因此可以使用链式调用处理多个异步操作
怎么办
创建promise对象
new Promise(excutor(resolve,reject))
- 初始化,接收执行器函数作为参数,
- 执行器函数的参数是两个函数(js内置),用来改变promise的状态
执行器函数是同步执行的
Promise.resolve()/reject()
- 一般情况下返回的是状态已经改变的promise
代码
基础用法
js
//1.基本用法
let promise = new Promise((resolve,reject)=>{
//异步操作
setTimeout(()=>{
let success=false;//异步操作的结果
if(success)
{
resolve('操作成功')//操作成功,传递结果
}else{
reject('操作失败')//操作失败,传递原因
}
},1000)
})
promise.then(res=>{
console.log(res);//操作成功时处理
}).catch(err=>{
console.log(err);//操作失败时处理
})
链式调用
js
//链式调用
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1)
},1000)
}).then((res)=>{
console.log(res); //1
return res*2;
}).then((res)=>{
console.log(res); //2
return res*2;
}).then((res)=>{
console.log(res); //4
}).catch(err=>{
console.log(err);
})
多个promise的并发处理
js
//3.多个promise并发处理
let promise1 = new Promise(resolve => setTimeout(() => resolve('Promise 1 完成'), 1000));
let promise2 = new Promise(resolve => setTimeout(() => resolve('Promise 2 完成'), 2000));
// Promise.all([promise1,promise2]).then((ress)=>{
// console.log(ress);//[ 'Promise 1 完成', 'Promise 2 完成' ]
// }).catch(err=>{
// console.log(err);
// })
// 使用 Promise.race 只等待第一个完成的 Promise
Promise.race([promise1, promise2]).then(result => {
console.log(result); // "Promise 1 完成"
}).catch(error => {
console.error(error);
});
与async/await结合使用
- async 声明一个函数是异步的
- await 暂停异步函数的执行,等待Promise解决后再继续执行。
js
//4. 与 async/await 结合使用
let promise1 = new Promise(resolve => setTimeout(() => resolve('Promise 1 完成'), 1000));
let promise2 = new Promise(resolve => setTimeout(() => resolve('Promise 2 完成'), 2000));
async function myPromise() {
try{
let result1 = await promise1; // 等待 promise1 完成
console.log(result1);
let result2 = await promise2; // 等待 promise2 完成
console.log(result2);
}catch (err){
console.log(err);
}
}
myPromise()