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

Node.js中media.pug页面无法渲染的问题排查与解决

问题排查与解决:media.pug页面无法渲染指定ID的图片和视频

我希望在media.pug页面展示服务器上每个已保存文件ID对应的图片和视频,但使用以下代码后页面无法正常渲染。

提交表单代码(Pug)

form(action="/medias/" + some_id method="GET")
    input(type="submit" value="Photo / Image")

some_id示例值为54

路由代码(Express)

router.get("/medias/:some_id" , InfoCtrl.apiMedias);

控制器代码(Node.js)

static async apiMedias(req, res, next) {
     try {
          const Id= req.params.some_id;
          const imagesPath = path.join(__dirname, `../public/media/${Id}/image`);
          const videosPath = path.join(__dirname, `../public/media/${Id}/video`);
          let images = [];
          let videos = [];

          function foo (folder, enconding)  {
                return new Promise(function(resolve, reject) {
                    fs.readdir(folder,enconding, function(err, filenames){
                        if (err) 
                            reject(err); 
                        else 
                            resolve(filenames);    
                    });
                });
            };

            foo(imagesPath).then((value)=>{
                 images= value;
            }).then(foo(videosPath).then((value)=>{
                     videos= value;
            }).then((value)=>{
                    var model =  {"phoneId": phoneId, "images": images , "videos": videos};
                    console.log(model);
                    res.render("media", {
                        "model": model,
                    });
            }));
        } catch (error) {
            console.log(error);
        }
    }

问题根源

  • Promise链式调用逻辑错误:你在then中嵌套了另一个Promise的then,导致异步执行顺序混乱。外层then不会等待视频目录读取完成就继续执行,可能导致videos为空,甚至res.render触发时机错误。
  • 未定义变量phoneId:model中的phoneId未声明,会抛出引用错误,但被try/catch捕获后仅打印日志,页面因无响应而渲染失败。
  • 参数拼写错误:foo函数里的enconding应为encoding,虽不致命但可能引发意外行为。
  • 错误处理不完善:若指定ID的目录不存在,fs.readdir报错后没有给客户端返回响应,页面会一直处于加载状态。

修复方案

1. 重构异步流程,用Promise.all并行读取目录

并行处理两个目录的读取,确保数据完整后再渲染页面,同时完善错误处理:

static async apiMedias(req, res, next) {
    try {
        const Id = req.params.some_id;
        const imagesPath = path.join(__dirname, `../public/media/${Id}/image`);
        const videosPath = path.join(__dirname, `../public/media/${Id}/video`);

        // 封装Promise版readdir,处理目录不存在的情况
        const readDir = (folder) => {
            return new Promise((resolve, reject) => {
                fs.readdir(folder, (err, filenames) => {
                    if (err) {
                        // 目录不存在时返回空数组,避免报错中断流程
                        err.code === 'ENOENT' ? resolve([]) : reject(err);
                    } else {
                        resolve(filenames);
                    }
                });
            });
        };

        // 并行读取图片和视频目录
        const [images, videos] = await Promise.all([
            readDir(imagesPath),
            readDir(videosPath)
        ]);

        // 修正phoneId变量,这里传入当前的ID
        const model = { phoneId: Id, images, videos };
        console.log(model);
        res.render("media", { model });
    } catch (error) {
        console.error(error);
        // 给客户端返回错误提示
        res.status(500).render("error", { message: "加载媒体文件失败" });
    }
}

2. 优化Pug表单语法

用模板字符串拼接action属性,避免语法歧义:

form(action=`/medias/${some_id}` method="GET")
    input(type="submit" value="Photo / Image")

3. 确保media.pug正确渲染资源

示例渲染逻辑,确保路径正确:

h1 媒体文件(ID: #{model.phoneId})
h2 图片列表
if model.images.length
    .image-grid
        each img in model.images
            img(src=`/media/${model.phoneId}/image/${img}` alt="媒体图片")
else
    p 暂无图片

h2 视频列表
if model.videos.length
    .video-list
        each vid in model.videos
            video(controls src=`/media/${model.phoneId}/video/${vid}`)
                p 您的浏览器不支持视频播放
else
    p 暂无视频

内容的提问来源于stack exchange,提问作者Javad-M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 00:10:20