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
相关产品推荐
相关产品推荐

