You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js异步图片下载时Promise数组处于pending状态的问题求解

问题解决方法

问题根源

你当前代码中imagePaths数组存储的是刚创建的异步下载任务对应的Promise实例,for循环仅负责创建异步任务,不会等待任务执行完毕,所以直接打印时所有Promise都处于pending状态,无法拿到实际下载后的文件路径。

修复方案

使用Promise.all()等待所有下载任务全部执行完成后,再执行后续逻辑。同时你现有代码存在两处隐性问题需要同步修复:

  • 自定义download方法的回调参数顺序不符合Node.js错误优先的回调规范,参数顺序写反会导致错误捕获失效
  • 保存文件时给文件名拼接了根据content-type生成的后缀,但resolve返回的是不带后缀的原始文件名,后续使用该路径会找不到文件,需要同步修正

修正后的核心代码

Template.findOne({ templateId: template_id }).exec()
        .then(template => {
            if (imageURLs.length !== template.requiredImages.count) {
                res.status(422).json({
                    status: "Fail",
                    message: "This template needed " + template.requiredImages.count + " image. But received " + imageURLs.length
                })
                // 终止后续Promise链执行,避免重复返回响应报错
                return Promise.reject('参数校验不通过')
            } else {
                return template;
            }
        })
        .then(template => {
            function naming(length) {
                var result = '';
                var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
                var charactersLength = characters.length;
                for (var i = 0; i < length; i++) {
                    result += characters.charAt(Math.floor(Math.random() * charactersLength));
                }
                return result;
            }
            var download = function (uri, filename, callback) {
                request.head(uri, function (err, res, body) {
                    if(err) return callback(err)
                    console.log('content-type:', res.headers['content-type']);
                    console.log('content-length:', res.headers['content-length']);
                    const ext = res.headers['content-type'].split('/')[1]
                    const fullFilename = filename + '.' + ext
                    request(uri).pipe(fs.createWriteStream(fullFilename)).on('close', () => {
                        // 返回带后缀的完整文件路径
                        callback(null, fullFilename)
                    });
                });
            };

            var downloadTasks = [];
            for (const imageURL of imageURLs) {
                downloadTasks.push(new Promise((resolve, reject) => {
                    let filename = __dirname + '/../../../downloads/' + naming(6)
                    download(imageURL, filename, function (err, fullFilename) {
                        if (err) reject(err);
                        else resolve(fullFilename)
                    });
                }))
            }
            // 批量等待所有下载任务完成
            return Promise.all(downloadTasks)
        })
        .then(imagePaths => {
            // 所有任务执行完成后才会进入该回调,imagePaths为下载完成的文件路径数组
            console.log(imagePaths);
            res.json("oki");
        })
        .catch(err => {
            // 统一捕获所有环节的错误
            console.error('处理出错:', err)
            if(!res.headersSent) {
                res.status(500).json({status: 'Fail', message: '处理失败'})
            }
        })

内容的提问来源于stack exchange,提问作者Süleyman Ali Akpınar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:12:02