- promise实例方法(定义在构造函数的原型对象上的方法)
- 1️⃣
Promise.prototype.then(onFulfilled, onRejected)- 2️⃣
Promise.prototype.catch(onRejected)- 3️⃣
Promise.prototype.finally(onFinally)- promise静态方法(直接定义在构造函数(类)上的方法)
- 4️⃣Promise.resolve
- 5️⃣Promise.reject
- 6️⃣Promise.all
- 7️⃣Promise.race
- 8️⃣Promise.allSettled
- ⑨Promise.any()
一、实际应用
1.1 !!创建Promise实例!!
- 必须传入一个执行器函数作为参数:
new Promise(); // 报错
- 函数接收两个参数:resolve,reject
resolve(异步返回的结果):将Promise对象的状态从pending变为resolved;reject():将Promise对象的状态从pending变为rejected- 只有当Promise的状态变为
resolved或者rejected时,才会执行实例方法or静态方法- promise内部发生错误,错误会被reject
对于概念的应用以及解释
// 传入执行器函数创建Promise实例
const myPromise = new Promise((reoslve, reject) => {
setTimeout(() => {
const success = true;
if(success){
resolve()
}else {
reject()
}
}, 3000)
})
// `resolve(异步返回的结果)`:将Promise对象的状态从pending变为resolved;`reject()`:将Promise对象的状态从pending变为rejected
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
})
console.log('1', promise1);
// ------'promise1' '1' Promise{<pending>}
// 只有当Promise的状态变为`resolved或者rejected`时,才会执行实例方法or静态方法
const promise = new Promise((resolve, reject) => {
console.log(1);
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
//。------ 结果:1 2 4
// promise内部发生错误,错误会被reject
const promise = new Promise(resolve => {
throw new Error("aa") // 等同于reject(new Error("aa"))
resolve("resolve");
});
console.log(promise) // Promise {<rejected>: Error: aa ...... }
1.2 1️⃣Promise.prototype.then(onFulfilled, onRejected)的使用
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。- Promise.prototype.then返回的是另外一个Promise实例
// 应用
promise.then(
value => {
// resolved时调用,value为resolve函数返回的参数
console.log(value);
},
err => {
// rejected时调用,err为reject函数返回的参数
console.log(err);
}
);
// 返回的是另外一个Promise的实例
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
resolve('resolve1')
})
const promise2 = promise1.then(res => {
console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);
// 结果: 'promise1' '1' Promise{<resolved>: 'resolve1'} '2' Promise{<pending>} 'resolve1'
1.3 2️⃣Promise.prototype.catch(onRejected) 的使用
-
catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。catch()方法也会返回一个 Promise 对象(同then方法)- 如果 Promise 状态已经变成
resolved,再抛出错误是无效的。 - promise中所有没有被处理的错误都会冒泡到最后一个catch中
- 如果 Promise 状态已经变成
-
实现“失败继续请求,请求n次不在继续请求”
// 模拟请求函数
const mockRequest = (): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const isSuccess = Math.random() < 0.3;
if (isSuccess) {
resolve('成功');
} else {
reject('失败');
}
}, 1000);
});
};
// 失败重复触发请求函数
const retryRequest = (maxRetries: number): Promise<string> => {
let attempt = 0;
const attemptRequest = (): Promise<string> => {
return new Promise((resolve, reject) => {
mockRequest()
.then(resolve)
.catch((error) => {
attempt++;
if (attempt >= maxRetries) {
reject(`请求失败 ${maxRetries} 次`);
} else {
console.log(`请求失败,重试第 ${attempt} 次`);
attemptRequest().then(resolve).catch(reject);
}
});
});
}
return attemptRequest();
};
retryRequest(3)
.then((res) => {
console.log('3 次之内请求成功:', res);
})
.catch((err) => {
console.log('3 次之内请求失败:', err);
});
1.4 4️⃣Promise.resolve 的使用5️⃣Promise.reject 的使用
Promise.resolve()返回一个以给定值解析后的Promise 对象。Promise.reject()方法会返回一个新的状态为rejected的Promise 实例
一、 Promise.resolve
参数分为一下四种情况
- promise实例
- thenable对象
- 非对象
- 参数为空
- 参数是promise实例,那么
Promise.resolve将不做任何修改,原封不动地返回这个实例。
const promise = new Promise((resolve, reject) => {
reject("resolve");
});
let p = Promise.resolve(promise);
console.log(p); // Promise { <rejected> "resolve" }
console.log(promise); // Promise { <rejected> "resolve" }
- 参数是thenable对象:具有
then方法的对象。Promise.resolve()方法会将这个对象转为Promise对象,然后立即执行thenable对象的then()方法- 返回的
Promise会“跟随”这个thenable对象,采用它的最终状态。
// thenable对象
let thenable = {
then(resolve, reject) {
reject(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(value => {
console.log("resolved", value);
}, err => {
console.log("rejected", err); // 42
});
- 非对象:
Promise.resolve()方法会返回一个状态为resolved的Promise对象,其resolved值即为传入的参数。
const p = Promise.resolve('Hello');
p.then(s => {
console.log(s); // Hello
});
- 参数为空:
Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的Promise对象。
Promise.resolve();
// 相当于
new Promise(resolve => resolve(undefined));
二、 Promise.reject
Promise.reject() 方法返回一个新的状态为 rejected 的 Promise 实例,即使是一个 resolved 状态的 Promise 也不行。
let promise = Promise.resolve("foo");
let p1 = Promise.reject(promise);
p1.then(value => {
console.log("resolved", value);
}, err => {
console.log("rejected", err); // Promise {<fulfilled>: 'foo'}
});
三、 关于链式调用(实例方法then;静态方法:reject,resolve的结合应用如下:【更好理解Promise的行为和工作机制】
- 未传入处理程序:
Promise.resolve("foo")创建了一个立即解决的Promise
const p1 = Promise.resolve("foo");
let pt1 = p1.then();
console.log(p1); // Promise { <resolved>: "foo" }
console.log(pt1); // Promise { <resolved>: "foo" }
p1.then()调用了then方法,但没有传入处理程序(即onFulfilled和onRejected都是undefined)。- 如果
then方法没有传入处理程序,它会返回一个新的Promise,该Promise会继承原始Promise的状态和值。因此,pt1将会解决为"foo",与p1的值相同。
- 未成功调用then方法
const p2 = Promise.reject("bar");
let pt2 = p2.then(value => {
console.log(value);
});
console.log(p2); // Promise { <rejected>: "bar" }
console.log(pt2); // Promise { <rejected>: "bar" }
Promise.reject("bar")创建了一个立即拒绝的Promise,其原因是"bar"。p2.then(value => { console.log(value); })调用了then方法,并传入了一个onFulfilled处理程序。- 由于
p2已经被拒绝,onFulfilled不会被调用,因此console.log(value)不会执行。 pt2是p2.then()返回的新Promise。因为p2被拒绝且then方法没有传入onRejected处理程序,pt2也会被拒绝,其原因与p2相同,即"bar"。
- 返回的是另外一个 Promise 的实例
const promise1 = new Promise((resolve, reject) => {
console.log('promise1');
resolve('resolve1');
});
const promise2 = promise1.then(res => {
console.log(res);
});
console.log('1', promise1); // Promise { <resolved>: "resolve1" }
console.log('2', promise2); // Promise { <pending> }
// 输出顺序:
// 'promise1'
// '1' Promise { <resolved>: "resolve1" }
// '2' Promise { <pending> }
// 'resolve1'
new Promise((resolve, reject) => { ... })创建了一个新的Promise对象。在执行器函数中,console.log('promise1')会立即执行,并且resolve('resolve1')会将promise1的状态设置为已解决,值为'resolve1'。promise1.then(res => { console.log(res); })返回了一个新的Promise对象promise2。then方法中的回调函数会在promise1解决后执行。console.log('1', promise1)会输出Promise { <resolved>: "resolve1" },因为promise1已经解决。console.log('2', promise2)会输出Promise { <pending> },因为promise2是由then方法返回的新Promise,此时它的状态是pending,直到then方法中的回调函数执行完毕。- 当
promise1解决后,then方法中的回调函数res => { console.log(res); }会被调用,输出'resolve1'。此时,promise2的状态将从pending变为resolved,其值为undefined,因为then方法中的回调函数没有返回值。
1.5 ⑥promise静态方法all的使用
-
Promise.all接受一个包含多个 Promise 实例的可迭代对象(通常是数组),并返回一个新的 Promise 实例。这些 Promise 实例会并行执行。Promise.all返回的 Promise 会在以下两种情况下被处理:- 全部成功:如果所有 Promise 都成功,则返回一个包含所有成功结果的数组。
- 任一失败:如果有任意一个 Promise 失败,则返回第一个失败的 Promise 的错误。
-
Promise.all: 用于需要所有异步操作都成功后才进行下一步操作的场景,并行获取多个API数据并在所有数据都获取成功后再处理
const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');
const promise3 = fetch('https://api.example.com/data3');
Promise.all([promise1, promise2, promise3])
.then((responses) => {
return Promise.all(responses.map(response => response.json()));
})
.then((data) => {
console.log(data); // 所有数据都成功获取
})
.catch((error) => {
console.error('有一个请求失败:', error);
});
1.6 7️⃣promise静态方法race的使用
页面分享是异步操作么?
是的!why?用户点击分享之后即使没有立马响应也不会阻塞其他操作。
// 分享函数的定义
export async function shareAsync(
url: string,
title: string
): Promise<boolean>{
// 超时机制,3s内没有执行分享操作,定时器Promise将会首先完成
// promise静态方法race
const reuslt = await Promise.race({
shareActivityAsync({ // 异步请求分享给微信好友
url,
title
}),
// promise实例的创建
new Promise(resolve => setTimeout(() => resolve(true), 3000))
})
return result as boolean;
}
// 调用分享函数
const success = await shareAsync(
url,
title
)
if(success){
toast('分享成功')
} else {
toast('分享失败请重试')
}
1.7 ⑧promise静态方法allSettled
Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束,参数与Promise.all()方法一样
let p2 = Promise.reject(2);
let promise = Promise.allSettled([1, p2, 3]);
promise.then(value => {
console.log(value); // [{status: "fulfilled", value: 1},{status: "rejected", reason: 2},{status: "fulfilled", value: 3}]
});
console.log(promise);
Promise.allSettled()的返回的promise实例状态只可能变成resolved,它的监听函数收到的参数是一个数组,该数组的每个成员都是一个对象,每一个对象都有status属性,该属性的值只可能是字符fulfilled或字符串rejectedfulfilled时,对象有value属性,rejected时有reason属性,对应两种状态的返回值。
1.8 ⑨Promise.any()
该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
Promise.any()跟Promise.race()方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而结束。
let p1 = Promise.reject(1);
let p2 = Promise.reject(2);
let promise = Promise.any([p1, p2, 3]);
promise.then(value => {
console.log(value); // 3
});
console.log(promise);
当所有的实例返回的状态都是rejected时,Promise.any()会返回一个的实例状态才为rejected
let p1 = Promise.reject(1);
let p2 = Promise.reject(2);
let promise = Promise.any([p1, p2]);
promise
.then(value => {
console.log(value);
})
.catch(value => {
console.log(value); // AggregateError: All promises were rejected
});
console.log(promise);
1.9 ⑩Promise.try()
实际开发中,经常遇到一种情况:不知道或者不想区分,函数f是同步函数还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理f抛出的错误。一般就会采用下面的写法。
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now
上面的写法有一个缺点,就是如果f是同步函数,那么它会在本轮事件循环的末尾执行。
鉴于这是一个很常见的需求,所以现在有一个提案,提供Promise.try方法替代上面的写法。
const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next
部分参考于: