
JavaScript Promise
Promise基础概念Promise 是一个代表异步操作最终完成或失败的对象。它有三种状态:pending(进行中)fulfilled(已成功)rejected(已失败)const promise = new Promise((resolve, reject) => { // 异步操作...
2024年12月30日
1.4千字
Promise基础概念
Promise 是一个代表异步操作最终完成或失败的对象。它有三种状态:
pending(进行中)fulfilled(已成功)rejected(已失败)
const promise = new Promise((resolve, reject) => {
// 异步操作
if (/* 操作成功 */) {
resolve(value);
} else {
reject(error);
}
});Promise 的基本用法
// 基本使用
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
}, 1000);
});
promise
.then(result => console.log(result)) // 处理成功
.catch(error => console.log(error)) // 处理错误
.finally(() => console.log("结束")); // 总是执行Promise实例方法

then catch finally
Promise.reject(123)
.then(res => console.info('then: ', res))
.catch(error => console.info('catch: ', error))
.finally(() => console.info('finally.'));Promise静态方法
静态方法返回的都是Promise实例对象和new Promise一样
- Promise.all 适合所有请求都必须成功的场景
- Promise.allSettled 允许部分失败,适合容忍部分请求出错的需求
- Promise.race 则常用于超时等情况
- Promise.all 存在错误即退出
all
成功的情况
Promise.all([
Promise.resolve(1),
new Promise(resolve => {
setTimeout(() => {
resolve(2)
}, 2000)
}),
Promise.resolve(3),
]).then(values => console.log(values));
失败的情况
console.group('>>> Promise start <<<')
Promise.all([
Promise.resolve(1),
new Promise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 2000)
}),
Promise.resolve(3),
]).then(values => console.log(values)).catch(error => console.error(error));
console.groupEnd()
一些使用场景
init: {
async all() {
const initPromises = [];
for (let fn in this) {
if (fn !== 'all') {
const result = this[fn]();
if (result instanceof Promise) {
initPromises.push(result);
}
}
}
await Promise.all(initPromises);
$('#submit').click();
}
···
}这种情况下,init下面如果有其他异步方法值的属性,如果all函数不改造为Promise.all的方式,按钮click会有可能执行不了好的,我来为您详细讲解 Promise 的相关知识
allSettled
等待所有都执行完,即便存在失败的情况
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface PromiseFulfilledResult<T> {
status: "fulfilled";
value: T;
}
interface PromiseRejectedResult {
status: "rejected";
reason: any;
}
type PromiseSettledResult<T> = PromiseFulfilledResult<T> | PromiseRejectedResult;
interface PromiseConstructor {
/**
* Creates a Promise that is resolved with an array of results when all
* of the provided Promises resolve or reject.
* @param values An array of Promises.
* @returns A new Promise.
*/
allSettled<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: PromiseSettledResult<Awaited<T[P]>>; }>;
/**
* Creates a Promise that is resolved with an array of results when all
* of the provided Promises resolve or reject.
* @param values An array of Promises.
* @returns A new Promise.
*/
allSettled<T>(values: Iterable<T | PromiseLike<T>>): Promise<PromiseSettledResult<Awaited<T>>[]>;
}
console.group('>>> Promise.allSettled >>>')
Promise.allSettled([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
reject(1)
}, 1000)
}),
]).then(values => console.log(values)).catch(error => console.error(error));
console.groupEnd()
race
console.group('>>> Promise <<<')
Promise.race([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
}),
]).then(values => console.log(values)).catch(error => console.error(error));
console.groupEnd()如果存在rejected状态的Promise
即便竟对结果是rejected,但是他不是首位跳出,也不会执行
Promise.race([
new Promise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
}),
]).then(values => console.log(values)).catch(error => console.error(error));
console.groupEnd()也和下面截图结果一样

any
存在错误即退出
console.group('>>> Promise.any >>>')
Promise.any([
new Promise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
}),
]).then(values => console.log(values)).catch(error => console.error(error));
console.groupEnd()
resolve
Promise.resolve(123).then(res => console.info('then: ', res)).catch(error => console.info('catch: ', error));reject
Promise.reject(123).then(res => console.info('then: ', res)).catch(error => console.info('catch: ', error));try
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/try
withResolvers
async/await 语法糖
// async/await 使异步代码更易读
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('获取数据失败:', error);
}
}const asyncFun = async () => {
try {
await Promise.resolve(123);
return 333;
} catch (error) {
return Promise.reject(error);
} finally {
console.info('finally');
}
}
console.info('asyncFun instance: ', asyncFun())
错误处理
// 错误处理方式
async function handleErrors() {
try {
await Promise.reject('出错了');
} catch (error) {
console.log('捕获到错误:', error);
}
}
// 或者使用 .catch()
new Promise((resolve, reject) => {
reject('出错了');
})
.catch(error => {
console.log('捕获到错误:', error);
});实际应用示例
// 实际应用场景
async function loadUserData() {
try {
// 并行请求
const [userInfo, userPosts] = await Promise.all([
fetch('/api/user'),
fetch('/api/posts')
]);
// 串行处理结果
const userData = await userInfo.json();
const postsData = await userPosts.json();
return {
user: userData,
posts: postsData
};
} catch (error) {
console.error('加载用户数据失败:', error);
throw error;
}
}const utils = {
/**
* 获取看板指定接口
* 获取PC033012配置,根据配置决定是否返回新接口
* @param {String} oldUrl 旧接口url
* @param {String} newUrl 新接口url
* @returns {Promise<String>}
*/
getBoardUrlWithSetting(oldUrl, newUrl) {
if (boardUtils.boardUrlSettingCacheValue !== null) {
console.info('读PC033012配置缓存值: ', boardUtils.boardUrlSettingCacheValue);
return Promise.resolve(boardUtils.boardUrlSettingCacheValue === '1' ? newUrl : oldUrl);
}
if (boardUtils._boardUrlSettingPromise) {
return boardUtils._boardUrlSettingPromise
.then(() => {
console.info('等待获取PC033012配置缓存值: ', boardUtils.boardUrlSettingCacheValue);
return boardUtils.boardUrlSettingCacheValue === '1' ? newUrl : oldUrl; // 直接返回 URL 字符串
})
.fail(error => {
console.error('[MRP] getBoardUrlWithSetting error:', error);
boardUtils._boardUrlSettingPromise = null;
return oldUrl;
});
}
boardUtils._boardUrlSettingPromise = boardUtils.getBoardMrpConfig('PC033012')
.then(config => {
if (config && config.data && config.data.value) {
const value = config.data.value;
boardUtils.boardUrlSettingCacheValue = value;
console.info('首次获取PC033012配置值: ', value);
boardUtils._boardUrlSettingPromise = null;
return Promise.resolve(value === '1' ? newUrl : oldUrl);
} else {
return Promise.resolve(oldUrl);
}
})
.fail(error => {
console.error('[MRP] getBoardUrlWithSetting error:', error);
boardUtils._boardUrlSettingPromise = null;
return oldUrl;
});
return boardUtils._boardUrlSettingPromise;
},
/**
* 是否使用看板新接口 for 有的看板新接口请求类型也变了
* @returns {String} '0' 使用旧接口 '1' 使用新接口
*/
getBoardNewUrlFlag() {
return boardUtils.getBoardUrlWithSetting('0', '1');
},
_boardUrlSettingPromise: null,
boardUrlSettingCacheValue: null,
}重要提示
- Promise 状态一旦改变就不能再变
.then()和.catch()总是返回新的 Promise- 异步操作应该优先考虑使用 Promise 而不是回调
async/await让异步代码更容易理解和维护- 记得始终处理 Promise 的错误情况
这些是 Promise 的核心概念和使用方法,掌握这些可以帮助您更好地处理 JavaScript 中的异步操作。

文章评论区
欢迎留言交流