让我们的目标保持简单但足够现实:用户可以通过浏览器使用我们的应用程序。当用户请求http://domain/start时,可以看到一个欢迎页面,页面上有一个文件上传表单。让我们分解这个应用程序。为了实现上述用例,我们需要实现哪些部分?1.我们需要提供网页,所以需要一个HTTP服务器2.对于不同的请求,根据请求的URL,我们的服务器需要给出不同的响应,所以我们需要一个对应请求的路由3.请求处理程序(requesthandler)4.当请求被服务器接收到并通过路由传递时,需要对其进行处理,所以我们需要最终的请求处理器5.路由还应该能够处理POST数据,并将数据封装成一个更友好的格式传递给请求处理程序,所以需要请求数据处理函数————————————————————————————————————————————————对于Node.js,在使用Node.js的时候,我们不仅仅是在实现一个应用,更是在实现整个HTTP服务器。其实我们的web应用和对应的web服务器基本是一样的。现在让我们开始实施之路,从第一部分开始——HTTP服务器。所以,现在让我们创建一个启动我们的应用程序的主文件,以及一个包含我们的HTTP服务器代码的模块。在我看来,调用主文件index.js或多或少是标准的。将服务器模块放在一个名为server.js的文件中是有意义的。让我们先从服务器模块开始。在项目的根目录中创建一个名为server.js的文件并编写以下代码:varhttp=require("http");http.createServer(function(request,response){response.writeHead(200,{"Content-Type":"text/plain"});response.write("HelloWorld");response.end();}).listen(8888);nodeserver.js接下来打开浏览器访问http://localhost:8888/,你会看到一个写着“HelloWorld”的网页。解析HTTP服务器接下来,让我们来分析一下这个HTTP服务器的组成。第一行需要Node.js自带的http模块,并将其赋值给http变量。接下来我们调用http模块提供的一个函数:createServer。此函数返回一个对象,该对象具有一个名为listen的方法,该方法采用一个数字参数来指定HTTP服务器正在侦听的端口号。我们暂时忽略http.createServer括号中的函数定义。我们可以使用这样的代码来启动服务器并监听端口8888:varhttp=require("http");varserver=http.createServer();server.listen(8888);当我们使用http.createServer方法时当然,我们不只是希望服务器监听某个端口,我们还希望它在服务器收到HTTP请求时做一些事情。问题是,这是异步的:请求可以随时到达,但我们的服务器是在单个进程中运行的。在编写PHP应用程序时,我们完全不用担心这一点:每当有请求进来时,Web服务器(通常是Apache)都会为这个请求创建一个新的进程,并从头到尾开始执行相应的PHP脚本。那么在我们的Node.js程序中,当一个新的请求到达8888端口时,我们如何控制进程呢?好吧,这就是Node.js/JavaScript的事件驱动设计真正有用的地方——尽管我们仍然需要学习一些新概念来掌握它。让我们看看这些概念如何应用到我们的服务器代码中。我们创建服务器并将一个函数传递给创建它的方法。每当我们的服务器收到请求时,都会调用此函数。我们不知道什么时候会发生这种情况,但我们现在有一个地方可以处理请求:它是我们将它传递给的函数。它是预定义函数还是匿名函数都没有关系。这就是传说中的回调。我们将一个函数传递给一个方法,当相应的事件发生时,该方法会调用这个函数作为回调。当回调触发并且我们的onRequest()函数被触发时,会传入两个参数:request和response。它们是对象,您可以使用其方法来处理HTTP请求的详细信息并响应请求(例如将某些内容发送回请求浏览器)。所以我们的代码是:当收到一个请求时,使用response.writeHead()函数发送一个HTTP状态200和HTTP头的content-type,并使用response.write()函数发送HTTP对应的正文“HelloWorld”。最后,我们调用response.end()来完成响应。我们将服务器脚本放在一个名为start的函数中,然后导出该函数。varhttp=require("http");functionstart(){functiononRequest(request,response){console.log("Requestreceived.");response.writeHead(200,{"Content-Type":"text/plain"});response.write("你好世界");响应结束();}http.createServer(onRequest).listen(8888);console.log("服务器已经启动。");}exports.start=start;创建一个index.js文件并写入以下内容:varserver=require("./server");server.start();就是这样。我们现在可以从我们的主脚本启动我们的应用程序,它仍然是一样的:nodeindex.js很棒,我们现在可以将我们应用程序的不同部分放入不同的文件中,并通过将它们连接在一起的方式生成模块。处理不同的HTTP请求是我们代码中称为“路由”的不同部分-因此,接下来让我们创建一个名为路由的模块。如何进行请求的“路由”?我们需要向路由提供请求的URL和其他需要的GET、POST参数,然后路由需要根据这些数据执行相应的代码(这里的“代码”对应整个应用的第三部分:一系列收到请求时实际工作的处理程序)。因此,我们需要查看HTTP请求并从中提取请求的URL和GET/POST参数。这个功能究竟应该属于路由还是服务器(甚至作为一个模块本身的功能)确实值得讨论,但这里暂定为我们HTTP服务器的功能。我们需要的所有数据都将包含在请求对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,分别是url和querystring模块。现在我们可以写路由了,创建一个名为router.js的文件,添加如下内容:console.log("Abouttoroutearequestfor"+pathname);}exports.route=route;```varhttp=require("http");varurl=require("url");functionstart(route){functiononRequest(request,response){varpathname=url.parse(request.url).pathname;console.log("请求for"+pathname+"received.");route(pathname);response.writeHead(200,{"Content-Type":"text/plain"});response.write("HelloWorld");response.end();}http.createServer(onRequest).listen(8888);console.log("服务器已经启动。");}exports.start=start;`同时,我们也会对index.js做相应的扩展,这样就可以在服务端注入路由函数了:varrouter=require("./router");服务器.start(路由器.route);像这样,我们传递一些东西,服务器用它来做一些事情。嗨,那个叫做路由的东西,你能帮我路由吗?但是服务器并不真的需要这样的东西。它只需要把事情做好,而为了把事情做好,你根本不需要事情,你需要的是行动。也就是说,你不需要名词,你需要动词。理解了这个概念中的核心和基本思想转换之后,自然就理解了函数式编程。详情请参考https://www.nodebeginner.org/...
