0

0

JavaScript中Promise.allSettled任务计时与性能分析

心靈之曲

心靈之曲

发布时间:2025-11-06 23:46:01

|

1024人浏览过

|

来源于php中文网

原创

JavaScript中Promise.allSettled任务计时与性能分析

本文探讨了如何在javascript中使用`promise.allsettled`并发执行任务时,精确测量每个独立promise的完成时间。通过两种不同的实现方式,我们可以获取任务耗时,从而深入分析异步操作的性能瓶颈,为优化api调用、批处理等场景提供数据支持,提升应用程序的响应性和效率。

在现代Web开发中,我们经常需要并发执行多个异步操作,例如同时请求多个API接口。Promise.allSettled是一个非常有用的工具,它允许我们等待所有Promise完成(无论成功或失败),并返回每个Promise的结果状态。然而,在某些场景下,我们不仅关心所有任务是否完成,更希望了解每个任务具体耗时多久。这对于性能分析至关重要,例如,当我们需要判断是否值得将一组API请求拆分为多个批次,以优先处理那些快速完成的任务时。

为什么需要对Promise进行计时?

对并发执行的Promise进行单独计时,可以帮助我们:

  • 识别性能瓶颈: 找出耗时最长的异步操作。
  • 优化资源分配: 根据任务耗时特点,调整并发策略,例如将耗时相近或相互依赖的任务分组。
  • 用户体验分析: 了解不同操作对用户等待时间的影响。
  • 服务质量监控: 持续跟踪外部服务或内部模块的响应时间。

实现Promise.allSettled的计时功能

以下将介绍两种在Promise.allSettled中集成任务计时的方法。

方法一:通过控制台日志输出计时结果

这种方法简单直接,它在每个Promise完成时,立即通过控制台输出其耗时。计时结果不会作为Promise.allSettled的最终返回值的一部分。

立即学习Java免费学习笔记(深入)”;

/**
 * 包装Promise数组,使其在完成时记录并输出耗时。
 *
 * @param {Array<Promise>} promises 待执行的Promise数组。
 * @returns {Promise<Array<Object>>} Promise.allSettled的原始结果。
 */
function allSettledTimedAndLogged(promises) {
    const start = Date.now(); // 记录整个批次开始时间

    return Promise.allSettled(promises.map((p, index) => {
        // 使用.finally()确保无论Promise成功或失败,都能记录时间
        return p.finally(() => {
            console.log(`[任务 ${index}] 完成,耗时 ${Date.now() - start}ms`);
        });
    }));
}

示例用法:

AI Web Designer
AI Web Designer

AI网页设计师,快速生成个性化的网站设计

下载
const task1 = new Promise(resolve => setTimeout(() => resolve('Task 1 Done'), 1000));
const task2 = new Promise((_, reject) => setTimeout(() => reject('Task 2 Failed'), 500));
const task3 = new Promise(resolve => setTimeout(() => resolve('Task 3 Done'), 1500));

console.log('开始执行并发任务...');
allSettledTimedAndLogged([task1, task2, task3])
    .then(results => {
        console.log('所有任务完成,Promise.allSettled结果:', results);
    });

// 预期控制台输出(顺序可能因Promise完成时间而异):
// 开始执行并发任务...
// [任务 1] 完成,耗时 ~1000ms
// [任务 0] 完成,耗时 ~500ms (如果任务2先完成)
// [任务 2] 完成,耗时 ~1500ms
// 所有任务完成,Promise.allSettled结果: [...]

注意事项:

  • 此方法记录的是相对于整个批次开始时间的耗时,而非每个Promise独立启动的耗时。在并发场景下,这通常是我们更关心的指标。
  • 计时信息直接打印到控制台,不方便进行后续的程序化处理。

方法二:将计时结果嵌入到Promise.allSettled的返回数据中

如果需要将每个Promise的耗时作为其结果的一部分返回,以便后续处理或分析,可以采用以下方法。这通过在Promise.allSettled的结果处理阶段,将预先记录的耗时数据合并进去实现。

/**
 * 包装Promise数组,使其在完成时记录耗时,并将计时结果嵌入到Promise.allSettled的返回数据中。
 *
 * @param {Array<Promise>} promises 待执行的Promise数组。
 * @returns {Promise<Array<Object>>} 包含每个Promise状态和耗时的结果数组。
 */
function allSettledTimed(promises) {
    const start = Date.now(); // 记录整个批次开始时间
    const times = new Array(promises.length); // 用于存储每个Promise的耗时

    // 包装每个Promise,使其在完成时记录耗时
    const wrappedPromises = promises.map((p, index) => {
        return p.finally(() => {
            times[index] = Date.now() - start; // 记录相对于批次开始时间的耗时
        });
    });

    // 等待所有Promise完成,然后将计时数据合并到结果中
    return Promise.allSettled(wrappedPromises).then(results => {
        // 遍历结果数组,将对应的耗时添加到每个结果对象中
        for (let i = 0; i < results.length; i++) {
            results[i].time = times[i]; // 添加自定义的'time'属性
        }
        return results;
    });
}

示例用法:

const apiCall1 = new Promise(resolve => setTimeout(() => resolve({ id: 1, data: 'User A' }), 1200));
const apiCall2 = new Promise((_, reject) => setTimeout(() => reject(new Error('Network Error')), 600));
const apiCall3 = new Promise(resolve => setTimeout(() => resolve({ id: 3, data: 'Product X' }), 800));

console.log('开始执行带计时的并发API调用...');
allSettledTimed([apiCall1, apiCall2, apiCall3])
    .then(results => {
        console.log('所有API调用完成,结果(含计时):', results);
        // 进一步分析结果
        results.forEach((res, index) => {
            if (res.status === 'fulfilled') {
                console.log(`API ${index + 1} 成功,耗时 ${res.time}ms,值:`, res.value);
            } else {
                console.log(`API ${index + 1} 失败,耗时 ${res.time}ms,原因:`, res.reason.message);
            }
        });

        // 查找最慢的任务
        const slowestTask = results.reduce((prev, current) => (prev.time > current.time ? prev : current));
        console.log('最慢的任务耗时:', slowestTask.time, 'ms');
    });

// 预期控制台输出:
// 开始执行带计时的并发API调用...
// 所有API调用完成,结果(含计时): [
//   { status: 'fulfilled', value: { id: 1, data: 'User A' }, time: ~1200 },
//   { status: 'rejected', reason: Error: Network Error, time: ~600 },
//   { status: 'fulfilled', value: { id: 3, data: 'Product X' }, time: ~800 }
// ]
// API 1 成功,耗时 ~1200ms,值: { id: 1, data: 'User A' }
// API 2 失败,耗时 ~600ms,原因: Network Error
// API 3 成功,耗时 ~800ms,值: { id: 3, data: 'Product X' }
// 最慢的任务耗时: ~1200 ms

注意事项:

  • 此实现假设传入的是一个数组(以便使用.map())。如果需要支持任意可迭代对象,则需要额外的代码进行转换。
  • Date.now()提供了毫秒级的精度,对于大多数性能分析场景已经足够。对于需要更高精度的场景,可以考虑使用performance.now()(但它返回的是高精度时间戳,通常用于测量网页加载或脚本执行时间)。
  • 这种方法返回的结果结构更丰富,便于后续的自动化处理和报告生成。

总结

通过上述两种方法,我们可以在使用Promise.allSettled进行并发任务管理时,有效地测量每个任务的执行时间。方法一适用于快速调试和日志记录,而方法二则提供了更结构化的数据,便于进行深入的性能分析和程序化决策。选择哪种方法取决于具体的应用场景和对计时数据处理的需求。掌握这些技术,将有助于开发者更好地理解和优化异步JavaScript应用的性能表现。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1958

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

658

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2401

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

47

2026.01.19

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

40

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

47

2025.11.27

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号