2016-09-25 35 views
0

所以,我有我的快遞(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()的信號來表示響應結束,爲什麼它不會在所有正常的getpost上做這些事情並將它們保持打開狀態?

因爲:

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

正常工作和response根據瀏覽器已經完成....

回答

1

你可以做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()將在未來被調用。它只能知道它是否已被調用。

+0

所以基本上,連接保持打開狀態,直到你在'response'上發送''或'json'的東西或超時。 –

+0

@CallumLinington是的。但是對於超時(在Express方面),你必須使用一個像'connect-timeout'這樣的中間件,其中'var timeout = require('connect-timeout'); app.use(timeout('5s'));'或者類似的東西。否則Express將等待客戶端的超時或TCP連接的超時。 – rsp

+0

哦,對,那是一顆寶石! –

相關問題