节点Express ejs错误: 在视图目录中查找视图"error"失败

4

我正在使用ejs和mongoose制作一个express应用程序。

我遇到了以下错误:

 Error: Failed to lookup view "error" in views directory "/Users/ben/Documents/csMSc/web/site/app/views"
at EventEmitter.app.render (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/application.js:555:17)
at ServerResponse.res.render (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:938:7)
at module.exports (/Users/ben/Documents/csMSc/web/site/app/app.js:94:7)
at Layer.handle_error (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/layer.js:58:5)
at trim_prefix (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:300:13)
at /Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:270:7
at Function.proto.process_params (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:321:12)
at IncomingMessage.next (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:261:10)
at fn (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:933:25)
at EventEmitter.app.render (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/application.js:557:14)
at ServerResponse.res.render (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:938:7)
at app.use.res.render.message (/Users/ben/Documents/csMSc/web/site/app/app.js:83:9)
at Layer.handle_error (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/layer.js:58:5)
at trim_prefix (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:300:13)
at /Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:270:7
at Function.proto.process_params (/Users/ben/Documents/csMSsc/web/site/app/node_modules/express/lib/router/index.js:321:12)   

从两个调用res.render()中获取数据,该数据来自mongoose查询,例如:

  if(req.query.author !== undefined) {
        var author = req.query.author;
        Post.find().where('author').equals(author).sort({ created: -1 }).limit(10).exec(function(err, authorsPosts) {
            if (err) return res.send("error");
            if(authorsPosts.length==0) {
                res.render('pages/index', {
                    viewDataSignStatus: viewDataSignedIn[signedIn],
                    previews: authorsPosts,
                    error: "Sorry there are no posts with that tag."
                });
            } else {
                res.render('pages/index', {
                    viewDataSignStatus: viewDataSignedIn[signedIn],
                    previews: authorsPosts
                });
            }
        });
    }

另一个查询相同,只不过带有一个查询:

    Post.find( { tags : { $elemMatch: { $in : tagList } } } ).limit(10).exec(function(err, taggedPosts) {

然而,除了同一函数中稍后的一个调用,我在此视图上的其他所有渲染调用都正常工作:
 //or just latest
    Post.find().sort({ created: 1 }).limit(10).exec(function(err, latestPosts) {
        if (err) return res.send(err);
        res.render('pages/index', {
            viewDataSignStatus: viewDataSignedIn[signedIn],
            previews: latestPosts
        });
    });

我很确定latestPosts的格式与以上作者帖子的格式完全相同。

没有调用渲染名为error的视图。

传递给上述一些res.render('pages/index')调用的错误数据是使用自定义过滤器传递的。

//custom ejs filter, sets to default value if data not supplied
ejs.filters.get = function(obj, prop, def) {
  return obj[prop] === undefined ? def : obj[prop];
};

该代码出现在app/views/pages/index.ejs文件中。

<p><%=: locals | get:'error','' %> </p>

我的ejs设置如下:

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs').renderFile);

以下是整个有问题的路由函数,它十分糟糕

router.get('/', function(req, res, next) {
    var accountController = new AccountController(User, req.session);
    console.log("here1");
    var signedIn = accountController.session.userProfileModel !== undefined ? 1 : 0;
    console.log("here2");

    //Author search
    if(req.query.author !== undefined) {
        var author = req.query.author;
        Post.find().where('author').equals(author).sort({ created: -1 }).limit(10).exec(function(err, authorsPosts) {
            if (err) return res.send("error");
            console.log("\n\nAuthorsPosts:" +authorsPosts);
            console.log("\n\authorsPosts.length: " +authorsPosts.length);
            console.log("authors post.constructor = " +authorsPosts.constructor);
            if(authorsPosts.length==0) {
                console.log("length=0");
                res.render('pages/index', {
                    viewDataSignStatus: viewDataSignedIn[signedIn],
                    previews: authorsPosts,
                    error: "Sorry there are no posts with that tag."
                });
            } else {
                res.render('pages/index', {
                    viewDataSignStatus: viewDataSignedIn[signedIn],
                    previews: authorsPosts
                });
            }
        });
    }
    //Tag search
    if(req.query.filter !== undefined) {
        var tagList = req.query.filter.constructor == Array ? req.query.filter : req.query.filter.split(",");
        Post.find( { tags : { $elemMatch: { $in : tagList } } } ).limit(10).exec(function(err, taggedPosts) {
            if (err) return res.send("error");
            console.log("\n\taggedPosts.length: " +taggedPosts.length);
            if(taggedPosts.length==0) {
                console.log("length=0");

                res.render('pages/index', {
                    viewDataSignStatus: viewDataSignedIn[signedIn],
                    previews: taggedPosts,
                    error: "Sorry there are no posts with that tag."
                });
            } else {
                console.log("\n\ntaggedPosts:\n\n" +taggedPosts);
                res.render('pages/index', {
                    viewDataSignStatus: viewDataSignedIn[signedIn],
                    previews: taggedPosts
                });
            }
        });
    }
    //or just latest
    Post.find().sort({ created: 1 }).limit(10).exec(function(err, latestPosts) {
        if (err) return res.send(err);
        res.render('pages/index', {
            viewDataSignStatus: viewDataSignedIn[signedIn],
            previews: latestPosts
        });
    });
});

此外,它并非完全无法工作。当代码执行到那些渲染呼叫时,会抛出错误,页面通常会冻结,您无法点击任何链接,然后如果我重新加载一次或两次,它就能正常工作,并使用正确的数据呈现模板。
此外,当我使用这些查询字符串之一前往'/'时,例如GET /?filter=Marc%20Behrens,它会打印所有返回的帖子,然后引发错误。
谢谢!
编辑:感谢Alex Ford。
新错误是:
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:690:11)
    at ServerResponse.header (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:700:10)
    at ServerResponse.send (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:154:12)
    at ServerResponse.json (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:240:15)
    at ServerResponse.send (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/response.js:142:21)
    at module.exports (/Users/ben/Documents/csMSc/web/site/app/app.js:100:9)
    at Layer.handle_error (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/layer.js:58:5)
    at trim_prefix (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:300:13)
    at /Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:321:12)
    at next (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:261:10)
    at Layer.handle_error (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/layer.js:60:5)
    at trim_prefix (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:300:13)
    at /Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:321:12)
    at next (/Users/ben/Documents/csMSc/web/site/app/node_modules/express/lib/router/index.js:261:10)

你的新错误意味着你试图处理已经发送的响应。你在某个地方调用了 res.sendres.render,然后在稍后的时间又再次调用了它。你能否发布一个更完整的应用程序代码示例,或者如果它是公开的,甚至可以提供存储库链接?我很乐意进行调查。 - Chev
是的,我自己也看不到它发生在哪里。整个应用程序在这里:https://github.com/bcrabbe/songsphere 非常感谢! - bcrabbe
4个回答

3
您遇到了一个错误,而默认的Express错误处理程序正在尝试通过渲染错误视图向用户显示该错误。您是否使用生成器来生成初始应用程序?如果是这样,您是否从视图目录中删除了错误视图?
要么更改默认的Express错误处理程序(可能在您的app.js文件中),使其仅输出原始错误,而不是尝试将其渲染成漂亮的小视图,或者添加它正在寻找的错误视图。
由express-cli生成的错误处理程序通常如下所示:
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: err
  });
});

注意它试图渲染 'error' 但找不到名为 "error" 的视图。它成为错误处理程序的简单原因是它接受 4 个参数,第一个是错误。Express 知道如果捕获到错误,则应跳转到该处理程序。
至于导致错误处理程序运行的实际错误,我不确定。您需要修复它以正确显示错误,然后才能从那里进行调试。

谢谢!一直以来我都在想“为什么Node的错误提示这么不友好”。新的错误信息已经编辑好了。 - bcrabbe
太棒了,我很高兴能够帮助到你。如果解决了你的问题,请务必接受答案 ^_^ - Chev

3
我猜"headers already sent"错误的原因是你的// 或者只有最新的代码在上面的if语句运行时也在运行。如果情况如此,那么你肯定会多次调用res.renderres.send。试试这个方法:
router.get('/', function(req, res, next) {

  /* ... */

  //Author search
  if(req.query.author !== undefined) {
    /* ... */
      if(authorsPosts.length==0) {
        res.render(/*...*/);
      } else {
        res.render(/*...*/);
      }
    /* ... */
  }
  //Tag search
  else if(req.query.filter !== undefined) {
    /* ... */
      if(taggedPosts.length==0) {
        res.render(/*...*/);
      } else {
        res.render(/*...*/);
      }
    /* ... */
  }
  //or just latest
  else {
    res.render(/*...*/);
  }
});

太棒了!很高兴我能再次帮忙... :P - Chev

0

我遇到了这个错误,使用jsx引擎。通过确保我在视图文件夹中的文件具有正确的扩展名*.jsx(在我的情况下),我解决了这个问题。我之前只是将其命名为index.js


0
我做错的是在路由目录中省略了扩展名 .html。
router.get('/', function(req, res, next) {
    res.render('index');                 //change from index to index.html
});

router.get('/', function(req, res, next) {
    res.render('index.html');
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接