基于Jimp.js的异步资源加载:Promise链式优化与状态监听需求
嘿,我完全懂你现在的麻烦——用Jimp.js链式加载大量资源的时候,代码很容易变得嵌套杂乱,还不好追踪哪些资源失败、什么时候全部加载完成。咱们用Promise的原生方法就能轻松解决这个问题,而且代码会清爽很多!
首先得明确:Jimp的Jimp.read()方法本身就返回一个Promise,所以你完全不用自己手动再包一层Promise(除非有特殊的自定义逻辑),直接用它返回的Promise就行。
针对你的两个核心需求,最适合的工具是Promise.allSettled()——它会等待所有传入的Promise全部完成(不管成功还是失败),然后返回每个Promise的结果状态,完美契合你的需求。
下面是完整的可运行示例代码,我给你拆解清楚:
// 第一步:把所有要加载的资源路径整理成数组 const imageResources = [ './assets/avatar.png', './assets/banner.jpg', './assets/icon.svg', // 可以继续加更多资源路径 ]; // 第二步:把每个资源路径转换成Jimp加载的Promise // 这里我们提前处理每个Promise的成功/失败,返回带详细信息的对象 const loadTasks = imageResources.map(resourcePath => { return Jimp.read(resourcePath) .then(loadedImage => { // 成功时返回路径、状态和加载好的图片对象 return { path: resourcePath, isSuccess: true, image: loadedImage }; }) .catch(loadError => { // 失败时返回路径、状态和错误信息 return { path: resourcePath, isSuccess: false, error: loadError }; }); }); // 第三步:等待所有加载任务完成,统一处理结果 Promise.allSettled(loadTasks) .then(allResults => { // 到这里,所有资源都已经加载完成(成功或失败) console.log('✅ 所有资源加载任务已完成!'); // 分离成功和失败的结果,方便后续处理 const successfulLoads = allResults .filter(result => result.status === 'fulfilled' && result.value.isSuccess) .map(result => result.value); const failedLoads = allResults .filter(result => result.status === 'rejected' || !result.value.isSuccess) .map(result => result.value || result.reason); // 处理成功加载的资源 if (successfulLoads.length > 0) { console.log(`🎉 成功加载 ${successfulLoads.length} 个资源:`); successfulLoads.forEach(item => { // 这里可以对加载好的Jimp图片做任意处理,比如缩放、加水印、保存 // 示例:把图片缩放到200x200并保存 item.image.resize(200, 200) .write(`./processed/${item.path.split('/').pop()}`); console.log(`- ${item.path}`); }); } // 处理加载失败的资源 if (failedLoads.length > 0) { console.error(`❌ 有 ${failedLoads.length} 个资源加载失败:`); failedLoads.forEach(item => { console.error(`- ${item.path}: ${item.error?.message || '未知错误'}`); }); } });
为什么这个方案比链式加载好?
- 代码结构清晰:不用嵌套一堆
.then(),所有加载任务并行处理,逻辑一目了然。 - 完美满足你的需求:
- 所有资源完成时会触发
.then(),明确知道加载完成的时间点。 - 可以精准筛选出失败的资源,还能拿到具体的错误原因。
- 所有资源完成时会触发
- 加载效率更高:链式加载是串行的(加载完一个才开始下一个),而
Promise.allSettled()是并行加载所有资源,速度快很多。
如果你有特殊需求(比如只要有一个资源失败就立刻终止所有加载),那可以换成Promise.all(),但它会在第一个Promise失败时就reject,不过这种场景下就没法知道其他资源的加载状态了,所以还是allSettled()更适合你的需求。
内容的提问来源于stack exchange,提问作者CharlesW
相关产品推荐
相关产品推荐

