express和koa中的超时处理

xiaoxiao2021-02-28  53

从某个话题中得到的灵感,这里做一个分享, http://cnodejs.org/topic/592fdc2f03dba3510d8a62a0#59364c3b538dbcaa6bc7dd48 楼主遇到一个问题,如何管理express中的超时?

express中的超时处理

现成的模块有connect-time,有一百五十个star,在中间件中已经算不少了,下面是一段使用connect-time的代码

var express = require('express') var timeout = require('connect-timeout') var app = express() app.use(timeout('5s')) //....一些中间件 app.use(haltOnTimedout) // Add your routes here, etc. function haltOnTimedout (req, res, next) { if (!req.timedout) next() } app.listen(3000)

看起来很美好,然而实际上是有缺点的。

假设timeout的作用范围里中包含了一个名为query的中间件,长这个样子

function query(req, res, next) { setTimeout(function() { res.send('respond with a resource'); }, 10000); };

然后这样调用timeout

app.use(timeout('5s')) app.use(query) app.use(haltOnTimedout)

当然实际中可能是一个数据库操作或者别的,而且在某些情况下会因为阻塞让执行时间变得很慢,上面的代码中会在10秒后将数据返回前端,而这时timeout已经返回了一个超时相应,于是程序就gg了,报出一个Can’t set headers after they are sent的错误。


这个其实不能怪中间件,要怪express本身的机制,query中间件虽然加载了,然而里面的异步却不归timeout管。

这个问题有办法解决吗?一个思路是当timeout触发后,中断后面的异步操作,这个可以通过事件监听实现,然而很麻烦。

Koa中的timeout

所以说还是老老实实地用koa,能用同步写法就别写回调。 koa也有一些管理timeout的中间件例如koa-timeout,然而两三年没更新了,用的还是koa1.x的版本,好在也不是很难写,我就自己写了一个

var koa2-timeout = async function(ctx ,next){ var tmr = null; const timeout = 5000;//设置超时时间 await Promise.race([ new Promise(function(resolve, reject) { tmr = setTimeout(function() { var e = new Error('Request timeout'); e.status = 408; reject(e); }, timeout); }), new Promise(function(resolve, reject) { //使用一个闭包来执行下面的中间件 (async function() { await next(); clearTimeout(tmr); resolve(); })(); }) ]) }

核心思路是用promise.race来看定时器和后面全部的中间件哪个先跑完, * 如果定时器先跑完,返回错误信息,而且没有调用后续的next() * 如果后面的中间件先跑完….那就是正常执行没毛病

下面是个调用的例子

var koa = require("koa"); var app = new koa(); app.use(koa2-timeout); app.use(async (ctx,next)=>{ await myTimeout(1000);//这里如果改成6000就会返回超时信息 ctx.body = "end"; }) function myTimeout(ms) { return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } app.listen(3000);

其他的解决方案

仔细想想,还是有别的方案的,例如我们可以直接hack底层的res.end方法,只要在里面增加一个是否已经响应过的flag判断就好了。这里不再讲述

总结

Koa真是太好用了 比起express来koa的优点数不胜数

转载请注明原文地址: https://www.6miu.com/read-58900.html

最新回复(0)