Expressを使用してHTTPリクエストを処理するサーバー側のnode.jsアプリケーションを作成しており、websocket(socket.io)サポートを追加しています。ただし、HTTPサーバーを起動するコードにアクセスできません。さまざまなURLを処理するエクスプレスルーターと関数を作成しています。私のコードは次のようになります:
_var express = require('express');
var router = express.Router();
router.post( myURL, myFunction );
_
ルーターを設定するときに、socket.ioを使用してWebSocket接続もリッスンしたいと思います。 express
またはexpress()
をrequire('socket.io')( xxx )
に渡すことができません。http.Serverオブジェクトを渡す必要があります。しかし、サーバーを起動しなかったので、どうすれば入手できますか?
私の知る限り、Express app
オブジェクトはサーバーオブジェクトを認識していません。 Expressでの動作方法では、app
オブジェクトはサーバーオブジェクトに与えられ、その逆ではありません。実際、単一のapp
オブジェクトを複数のサーバーで使用することもできます(httpサーバーとhttpsサーバーで使用されることもあります)。
req.connection.server
を使用すると、リクエストハンドラー内からサーバーオブジェクトにアクセスできますが、サーバーからはリクエストのコンテキストの一部として取得されます。これは、app
オブジェクト自体が認識しているものではありません。
そのため、初期化時にsocket.ioで使用するためにサーバーオブジェクトにアクセスする場合は、サーバーオブジェクトを変数が作成される場所にキャプチャする必要があります。
質問に表示するコードはサーバーを作成または起動しません。 Expressで使用するサーバーを起動する通常の2つの方法は次のとおりです。
var express = require('express');
var app = express();
// Express creates a server for you and starts it
var server = app.listen(80);
または、サーバーを自分で作成し、ハンドラとしてExpressに渡します。
var express = require('express');
var app = express();
// you explicitly create the http server
var server = require('http').createServer(app);
server.listen(80);
これらのいずれの場合も、変数にサーバーオブジェクトが含まれ、socket.ioでそれを使用できます。
リクエストハンドラーに渡されるreq
またはres
オブジェクトからのリクエストの処理内で、Expressルートハンドラー内からサーバーにアクセスできます。
res.connection.server
req.connection.server
app.listen()
を呼び出すと、サーバーが返されます。例えば:
const server = app.listen(process.env.NODE_PORT, () => {
console.log('Listening', server.address());
});
簡単なラッパーを記述して、次のコードをファイルに追加することで、ExpressアプリでSocket IOインスタンスをインスタンス化または取得できます。
//Dependencies
const socketIo = require('socket.io');
//Placeholder for instance
let io;
//Export handler to instantiate or get instance
module.exports = function(server) {
if (server) {
io = socketIo(server);
}
return io;
};
次に、Expressを設定するときに、通常の方法でこのインスタンスをインスタンス化できます。
const app = require('express')();
const server = require('http').Server(app);
const io = require('./path-to-your-file')(server);
そして、後で別のルートやコードで必要になった場合は、次のようにして取得できます。
const io = require('./path-to-your-file')();
これはもちろん単純な例ですが、必要に応じてロジックを変更できます。
次のコードを使用して同じことを行うこともできます。
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(80);
詳細については、あなたが参照することをお勧めします このリンク
Wepack devServerをsocket-ioで使用したときにこの問題が発生し、jfriend00のコメントが役に立ちました。私はこのトリックを使います:
let server;
app.use((req, res, next) => {
if (!server){
server = req.connection.server;
//do fancy staffs with http-server
}
next();
})
express listen
関数の実装方法をご覧ください。
_app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
_
したがって、httpサーバーインスタンスを明示的に格納するかどうかは基本的に問題になりません。
_var server = require('http').createServer(app);
_
または、express listen
の戻り値を参照してください:
_var server = app.listen()
_
あなたは同じことを技術的に参照していますが、これはどうやら混乱しています... app.listen()
は基本的にhttp.Server(arguments)