javascript – ExpressJS不等我的承诺

我正在我的服务器上搜索页面.当到达端点并且用户等待搜索功能返回结果并呈现页面时,Express会转到404处理程序,而当我假设调用render函数时,我得到以下错误:

错误:发送后无法设置标头.

我究竟做错了什么?

router.get("/", async (req, res) => {
    try {
        const queryString = req.query.q;

        const user = helper.checkAndGetUser(req, res);

        let s = String(queryString), searchedTags = [""];
        if(s.indexOf(",") > -1){
            searchedTags = s.replace(" ", "").split(",");
        }

        const options = {
            "query": {tags: {$all: searchedTags}, _forSale: true}
        };

        const results = await Search.search(options).then(result => result).catch(err => {
            throw err;
        });

        //This res.render -call is called after the 404 splat-route.
        return res.render("partial/search.pug", {user: user, search: {
            query: queryString,
            results: results
        }});

        //If I'd use res.send for debugging, it is instead called before the splat-route, like the following:
        return res.send(results);
    } catch(err) {
        next(err);
    }
});

module.exports = router;

我注册了路由器:

const search = require("./search.js");
app.use("/search", search);

其次是404 splat-route:

app.get("*", async (req, res, next) => {

    const user = helper.checkAndGetUser(req, res);

    res.status(404);
    res.render("partial/404.pug", {user: user});
});

澄清:
我的问题是如何使res.render函数像res.send函数一样被调用?

更新[2017-10-05]:
我继续使用该网站的另一部分,一个类似的端点,并发现如果使用res.send而不是res.render,则发送由promise提供的结果按预期工作.使用res.render,404处理程序再次启动.这可能是Express中的错误吗?

解决方法:

如果您在发送res后尝试写入res,则会发生这种情况,因此您必须在res.render()之后调用其他代码,或者在调用之前已经响应.

将其更改为返回res.render(…)以便退出函数,否则它将继续通过该函数并命中其他res.render()等.

还有一些错误处理程序.我将在几分钟内通过提示(在电话上)更新我的帖子.它应该有(req,res,next)并调用return next(err)并将其传递给错误处理中间件.

这是我喜欢在async / await Express中使用的模式:

// these routes occur in the order I show them

app.get('/route', async (req, res, next) => {
    try {
        const data = 'asdf'
        const payload = await something(data)
            .then((result) => createPayload(result))

        // remember, if you throw anywhere in try block, it will send to catch block
        // const something = willFail().catch((error) => {
        //     throw 'Custom error message:' + error.message
        // })

        // return from the route so nothing else is fired
        return res.render('route', { payload })
    } catch (e) {
        // fire down to error middleware
        return next(e)
    }
})

// SPLAT
app.get('*', async (req, res, next) => {
    // if no matching routes, return 404
    return res.status(404).render('error/404')
})

// ERRORS
app.use(async (err, req, res, next) => {
    // if err !== null, this middleware fires
    // it has a 4th input param "err"
    res.status(500).render('error/500')
    // and do whatever else after...
    throw err
})

Note: next() callback called without param is treated as no error, and proceeds to the next middleware. If anything is passed in, it will fire the error middleware with the param as the value of err in the error handling middleware. You can use this technique in routes and other middlewares, as long as the error middleware comes last. Mind your use of return with res.send/render() to prevent double setting headers.

新:

看起来有些东西.then()有一个回调.我没有逻辑地看到err会来自哪里,因为已解析的promise的值作为结果进入.then()函数.此时,它是可疑的,如果可能应该删除或重构.这部分在这里:

try {
    let results = [];
    await Search.search(options).then(result => {
        results = result;
    }, err => {
        throw err;
    });

    console.log("res.render");
    return res.render("partial/search.pug", {user: user, search: {
        query: string,
        results: results
    }});
} catch(err) {
    next(err);
}

首先,这是关于我期望使用async / await语法看到的内容:

router.get("/", async (req, res, next) => {

    try {
        const queryString = req.query.q;
        const user = helper.checkAndGetUser(req, res);

        let s = String(queryString), searchedTags = [""];
        if (s.indexOf(",") > -1) {
            searchedTags = s.replace(" ", "").split(",");
        }
        const options = {
            "query": { tags: { $all: searchedTags }, _forSale: true }
        };

        // If a promise is ever rejected inside a try block,
        // it passes the error to the catch block.
        // If you handle it properly there, you avoid unhandled promise rejections.

        // Since, we have async in the route function, we can use await
        // we assign the value of Search.search(options) to results.
        // It will not proceed to the render statement
        // until the entire promise chain is resolved.
        // hence, then(data => { return data }) energizes `results`
        const results = await Search.search(options)
            .then(data => data)
            // If any promise in this chain is rejected, this will fire
            // and it will throw the error to the catch block
            // and your catch block should pass it through to your
            // error handling middleware
            .catch(err => { throw 'Problem occurred in index route:' + err });

        return res.render("partial/search.pug", {
            user: user, search: {
                query: string,
                results: results
            }
        });
    } catch (err) {
        // look at the top how we added next as the 3rd, callback parameter
        return next(err);
    }
});

module.exports = router;

错误处理程序

// notice how we add `err` as first parameter
app.use((err, req, res, next) => {

    const user = helper.checkAndGetUser(req, res);

    res.status(404);
    res.render("partial/404.pug", {user: user});
});

来自Express文档:

Define error-handling middleware functions in the same way as other middleware functions, except error-handling functions have four arguments instead of three: (err, req, res, next). For example:

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

http://expressjs.com/en/guide/error-handling.html

这可能是你真正的问题,因为错误处理程序应该只在使用任何输入调用next()时触发,但是你的每次都像正常的中间件一样被触发,所以我怀疑它是因为中间件函数没有错误的参数,所以它被视为正常的.

The Default Error Handler

Express comes with a built-in error handler, which takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack.

If you pass an error to next() and you do not handle it in an error handler, it will be handled by the built-in error handler; the error will be written to the client with the stack trace. The stack trace is not included in the production environment.

If you call next() with an error after you have started writing the response (for example, if you encounter an error while streaming the response to the client) the Express default error handler closes the connection and fails the request.

So when you add a custom error handler, you will want to delegate to the default error handling mechanisms in Express, when the headers have already been sent to the client:

// code example in docs

Note that the default error handler can get triggered if you call next() with an error in your code more than once, even if custom error handling middleware is in place.

我还建议在错误处理程序middlware(也就是列表中最后加载的路由)的正上方使用splat route app.get(‘*’,async(req,res,next)=> {}).这将捕获所有不匹配的路由,例如/ sih8df7h6so8d7f并将客户端转发到404.我认为错误处理程序middlware更适合于错误500和清除格式化类型错误,因为它为您提供了一个可以解析next的值的函数(错误)任何时候从路线调用它.

我通常使用JSON Web令牌进行身份验证失败(作为每个auth所需路由中的第一行代码):

if (!req.person) return res.status(403).render('error/403')

我意识到其中一些可能会炒你的假发批发,所以尝试所有这些东西,看看每一件作品,然后再确定你是否愿意使用它.

原文地址:https://codeday.me/bug/20190611/1216813.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


根据官网 入门 express
java叫接口control什么的app.get.post等等都是请求方式我们可以在游览器输入localhost端口/或者在Apifox里面写。
为了前端丢进去的时候可以直接判断中间件就是经过了这个就会被使用可以做一些自己的数据处理什么的。
Express 文件的上传和下载
运行命令下载app.js 增加中间件。
基本模板来的 后面用后就有什么加什么都行。
此篇完成 增删 刷新文件 的基本操作
最基本的创建 以及 添加了其他的一些插件 登录接口和四个接口
由于每个接口都要放就很麻烦 所以做个中间件
1importre234defstrip_operate(exp):#合并多余的操作符5exp=exp.replace("+-","-")6exp=exp.replace("--","+")7returnexp8910defcal_exp_son(exp_son):#计算两数的乘除11if&
 socket.html<script>//高级api不兼容socket.io//http单向的,socket是双向的,传输都靠tcpletsocket=newWebSocket('ws://localhost:3000')socket.onopen=()=>{//多个页面通信就是先发给服务器,服务器再发给另一个页面socket.send('我
M模式:类,表示数据的应用程序和使用验证逻辑以强制实施针对这些数据的业务规则。V视图:应用程序使用动态生成HTML响应的模板文件。C控制器:处理传入的浏览器请求的类中检索模型数据,然后指定将响应返回到浏览器的视图模板。简单练习: 1、添加ControllerHelloWorldControlle
在Node开发中免不了要使用框架,比如express、koa、koa2拿使用的最多的express来举例子开发中肯定会用到很多类似于下面的这种代码varexpress=require('express');varapp=express();app.listen(3000,function(){console.log('listen3000...');});app.use(middle
node的http创建服务与利用Express框架有何不同原生http模块与使用express框架对比:consthttp=require("http");letserver=http.createServer(function(req,res){//服务器收到浏览器web请求后,打印一句话console.log("recvreqfrombrowser");
编辑nginx文件vi/usr/local/etcginxginx.confnginx配置如下,配置后需重启nginxnginx-sreloadlocation~.*\.json{roothtml;add_header"Access-Control-Allow-Origin""*";}前端index.html<script>fetch('http://localhost:12
constexpress=require('express')constapp=express()//步骤的拆解constresult=express.static('./views')app.use(result)//再次托管一下样式表的资源目录app.use('/css',express.static('./css'))//托管JS文件目录app.use('/js&#
问题描述:最近在做毕设,express里边的中间件(body-parser)失效,req.body获取不到任何值,req.query能获取到值。一开始加body-parser中间件是有用的,直到昨天加了token之后,body-parser失效。试着把token去掉,无济于事,也不是这个问题,也有说版本对不上的,换了中间件的引入方法,还是没用!!! 后
express官网:---->传送门 expressexpress框架有许多功能,比如路由配置,中间件,对于想配置服务器的前端来说,非常便捷自从node发展之后,基于nodejs的开发框架也不断涌现出来,express就是其中之一,最近简单的写了点express框架的简单的处理请求的demo首先是安装express模块npminstall
目录问题: 操作:Win+S按键,输入“事件查看器”问题详情:模块DLLC:\ProgramFiles(x86)\IISExpress\aspnetcore.dll未能加载。返回的数据为错误信息。问题:  操作:Win+S按键,输入“事件查看器” 问题详情:模块DLLC:\ProgramFiles(x86)\IISExpress\aspnetcore.dll
//获取阿里云市场,快递物流记录https://market.aliyun.com/products/56928004/cmapi022273.html?spm=5176.2020520132.101.26.61f97218v18GBF#sku=yuncode1627300000//get_express_log(self::$config['web']['aliyun_AppCode']阿里云市场AppCode,缓存秒数如300秒,'快递公司代