异步快递中间件,它是如何知道
问题描述:
所以,我有我的快递(4.0)配置:异步快递中间件,它是如何知道
app.get('/api/tracks', (req, res) => {
});
在这里面我要查询elasticsearch:
app.get('/api/tracks', (req, res) => {
client.search({
index: 'someindex',
type: 'sometype',
body: {
query: {
match_all: {}
}
}
}, (err, resp) => {
res.json(resp);
});
});
这显然是一个“异步”因回调情况而提出要求。
如何快速知道流连,直到你送东西,因为所有帐户,该response
可能已发出时,搜索已经执行完毕....(前路的ES请求过完)
如果Express使用类似于某种事件的用法,所以调用类似res.end()
的信号来表示响应结束,为什么它不会在所有正常的get
或post
上做这些事情并将它们保持打开状态?
因为:
app.get('/api/profile', (req, res) => {
res.json({ user: 'callum' });
});
正常工作和response
根据浏览器已经完成....
答
你可以做res.json()
只有一次。考虑下面这个例子:
$ curl http://localhost:3333/json1
你2秒后得到这样的::
var express = require('express');
var app = express();
app.get('/json1', function (req, res) {
setTimeout(function() {
res.json({ok:true});
}, 2000);
});
app.get('/json2', function (req, res) {
setTimeout(function() {
res.json({ok:true});
res.json({ok:true});
}, 2000);
});
app.listen(3333);
当你访问它
{"ok":true}
但是,如果你试图用访问:
curl http://localhost:3333/json2
然后你仍然得到这个在你的c lient方:
{"ok":true}
但是你的服务器崩溃,并:
_http_outgoing.js:344
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
这意味着,快递等待res.json()
,一旦它得到一个完成的请求,但在那之后,你不能把它第二次。
与res.send()
相同 - 例如,看到那些路线:
app.get('/send1', function (req, res) {
setTimeout(function() {
res.send('ok');
}, 2000);
});
app.get('/send2', function (req, res) {
setTimeout(function() {
res.send('ok');
res.send('ok');
}, 2000);
});
在另一方面,似乎你可以调用res.end()
两次,第二呼叫被忽略:
app.get('/end1', function (req, res) {
setTimeout(function() {
res.end('ok');
}, 2000);
});
app.get('/end2', function (req, res) {
setTimeout(function() {
res.end('ok');
res.end('ok');
}, 2000);
});
但是如果你使用的res.write()
代替res.end()
那么请求将等待res.end()
和写不完:
app.get('/end1', function (req, res) {
setTimeout(function() {
res.end('ok');
}, 2000);
});
app.get('/end2', function (req, res) {
setTimeout(function() {
res.end('ok');
res.end('ok');
}, 2000);
});
但该消息实际上被交付 - 其中Y OU可以通过“\ n”结尾的消息观察,使curl
显示它时,它到达:
app.get('/write1', function (req, res) {
setTimeout(function() {
res.write('ok\n');
}, 2000);
});
app.get('/write2', function (req, res) {
setTimeout(function() {
res.write('ok\n');
res.write('ok\n');
}, 2000);
});
因此,大家可以看到,有一定的方式发送数据 - 像res.write()
,可多次使用并没有关闭连接。还有其他方式,如res.json()
只能使用一次,并且它们隐式关闭连接。
但是,如果你添加的路由像这样的:
app.get('/empty', function (req, res) {
});
然后快速将永远开放的连接等待,因为它没有办法知道是否res.end()
或res.json()
将在未来被调用。它只能知道它是否已被调用。
所以基本上,连接保持打开状态,直到你在'response'上发送''或'json'的东西或超时。 –
@CallumLinington是的。但是对于超时(在Express方面),你必须使用一个像'connect-timeout'这样的中间件,其中'var timeout = require('connect-timeout'); app.use(timeout('5s'));'或者类似的东西。否则Express将等待客户端的超时或TCP连接的超时。 – rsp
哦,对,那是一颗宝石! –