Node.js服务器.listen回调函数是什么?

5
我有一个node.js应用程序,我需要在服务器开始侦听时运行命令。关于server.listen的文档如下:
server.listen(port, [hostname], [backlog], [callback])
但是当我尝试使用此格式时,代码没有运行,但是没有出现错误消息。 这是我的应用程序中的监听部分:
var spawn = require('child_process').spawn
function listen(port) {
    try {
        server.listen(port, "localhost",511, function() {
          spawn("open",["http://localhost:"+port+"/"])
        })
    } catch (e) {
        listen(port+1)
    }
}



有些人要求查看我代码的全部内容,所以在这里:

var http = require("http"),
    path = require("path"),
    fs = require("fs"),
    mime = require("mime"),
    port = 1
var server = http.createServer(function(req, resp) {
    if (req.url == "/action" && req.headers["command"]) {
        resp.writeHead(200, {
            "Content-Type": "text/plain"
        });
        console.log("Command sent: " + req.headers["command"])
        try {
            var out = eval(req.headers["command"])
            if (typeof out == "object") {
                var cache = [];
                out = JSON.stringify(out, function(key, value) {
                    if (typeof value === 'object' && value !== null) {
                        if (cache.indexOf(value) !== -1) {
                            return "[Circular]";
                        }
                        // Store value in our collection
                        cache.push(value);
                    }
                    return value;
                });
            }
            resp.end(out);
        } catch (e) {
            resp.end(e.stack)
        }
    }
    var local = __dirname + "/public" + req.url
    if (fs.existsSync(local)) {
        if (fs.lstatSync(local).isDirectory(local)) {
            if (fs.existsSync(local + "/index.html")) {
                local += "/index.html"
                resp.writeHead(200, {
                    "Content-Type": mime.lookup(local)
                });
                fs.readFile(local, function(err, data) {
                    if (err) {
                        resp.writeHead(500, {
                            "Content-Type": "text/plain"
                        });
                        resp.end("Internal server error");
                        throw err;
                    }
                    resp.end(data)
                });
            } else {
                server.status_code = 403
                resp.writeHead(403, {
                    "Content-Type": "text/plain"
                });
                resp.end("GET 403 " + http.STATUS_CODES[403] + " " + req.url + "\nThat Directory has no Index")
                console.log("GET 403 " + http.STATUS_CODES[403] + " " + req.url)
            }
        } else {
            resp.writeHead(200, {
                "Content-Type": mime.lookup(local)
            });
            fs.readFile(local, function(err, data) {
                if (err) {
                    resp.writeHead(500, {
                        "Content-Type": "text/plain"
                    });
                    resp.end("Internal server error");
                    throw err;
                }
                resp.end(data)
            });
        }
    } else {
        if (req.url != "/action") {
            server.status_code = 404
            resp.writeHead(404, {
                "Content-Type": "text/plain"
            });
            resp.end("GET 404 " + http.STATUS_CODES[404] + " " + req.url + "\nThat File Cannot be found")
            console.log("GET 404 " + http.STATUS_CODES[404] + " " + req.url)
        }
    }
});
var spawn = require('child_process').spawn
function listen(port) {
    try {
        server.listen(port, "localhost")
    } catch (e) {
        listen(port+1)
    }
}

问题已解决!

通过结合 @mscdex 和 Peter Lyons 的答案,我已经解决了这个问题。

var spawn = require('child_process').spawn
server.listen(0,"localhost", function(err) {
    if(err) throw err;
    spawn("open",["http://localhost:"+server.address().port+"/"])

})

感谢你们两个


你能发布你的其余代码吗,特别是第一次调用 listen 的位置吗? - go-oleg
是的.. 服务器在哪里以及如何定义? - zipzit
4
如果您不需要监听特定的端口,可以使用0。然后在listen()回调函数中,可以通过server.address().port获取分配的端口号。 - mscdex
@Vulpus,我真的很希望通过这个示例学习更多关于Node的知识。除了我之外,还有其他人遇到了“NPM install spawn”的问题吗? - zipzit
@go-oleg 我的整个代码已经发布了。 - bren
@zipzit spawn来自于node核心的child-process模块,无需使用npm安装。 - Peter Lyons
1个回答

6
var spawn = require('child_process').spawn

function listen(port) {
  //Don't need try/catch here as this is an asynchronous call
  server.listen(port, "localhost", function(error) {
    if (error) {
      console.error("Unable to listen on port", port, error);
      listen(port + 1);
      return;
    }
    spawn("open",["http://localhost:"+port+"/"])
}
  • 我不确定你读的是什么文档,但官方的Node.js文档中 server.listen 的格式是server.listen(port, [host], [callback])
  • 你不需要使用try/catch,因为这是一个异步调用,错误会通过回调函数的第一个参数来表示。

请参见http://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback。 - bren
我的 Node 版本是 v0.11.14-pre,而文档是针对 v0.10.29 的,所以我认为他们可能已经对 server.listen 做出了更改。 - bren
将我的节点更新为v0.10.29并修改您的代码以具有正确数量的括号后,我仍然会收到EACCES错误。 - bren
EACCES表示端口被操作系统保留,因此只有sudo才能访问它(对于标准操作系统,它在1024以下),但我想能够给自己一个空闲端口并打开浏览器到该端口,但如果我不能保留该端口,则继续尝试下一个。 - bren
顺便提一下,使用sudo运行程序可以启动它,但是不允许浏览器访问该端口。 - bren
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接