簡體   English   中英

Async Express中間件,它怎么知道

[英]Async Express middleware, how does it know

所以我有Express(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);
    });
});

由於回調情況,這顯然是一個“異步”請求。

Express如何知道一直待在您發送東西之前,因為從所有帳戶來看, response可能是在搜索完成執行后發出的...。(在ES請求完成之前)

如果Express使用類似事件的用法,那么調用res.end()這樣的信號來表示響應結束,為什么它不對所有正常的getpost這樣做並保持打開狀態?

因為:

app.get('/api/profile', (req, res) => {
    res.json({ user: 'callum' });
});

正常工作,並且根據瀏覽器的response已完成。

您只能執行一次res.json() 考慮以下示例:

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);

當您通過以下方式訪問它時:

$ curl http://localhost:3333/json1

您在2秒鍾后收到此消息:

{"ok":true}

但是,如果您嘗試通過以下方式訪問它:

curl http://localhost:3333/json2

然后,您仍然可以在客戶端獲得此信息:

{"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)

這意味着Express等待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);
});

但是消息實際上已經傳遞了-您可以通過在消息末尾加上“ \\ 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) {
});

然后Express將永遠等待連接打開,因為它無法告知res.end()是否會調用res.end()res.json() 它只能知道它是否已經被調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM