美文网首页
NodeJS入门

NodeJS入门

作者: SpaceCat | 来源:发表于2022-11-05 23:37 被阅读0次

    1、什么是Node.js

    简单的说 Node.js 就是运行在服务端的 JavaScript。
    Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。
    Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。

    2、Node.js简单示例

    2.1 安装

    这里是在Mac OS上来安装node,使用 brew 命令来安装:

    brew install node
    

    2.2 Hello World

    在一个目录中,新建一个index.js文件,内容如下:

    const http = require('http');  
    const hostname = '127.0.0.1';  
    const port = 3000;  
    const server = http.createServer((req, res) => {  
        res.statusCode = 200;  
        res.setHeader('Content-Type', 'text/plain');  
        res.end('Hello World');  
    });  
    server.listen(port, hostname, () => {  
        console.log(`Server running at http://${hostname}:${port}/`);  
    });
    

    这个代码中实际上使用了匿名函数,换成如下代码,效果一样,更容易理解:

    const http = require('http');  
    const hostname = '127.0.0.1';  
    const port = 3000;  
    function onRequest(req, res){  
        res.statusCode = 200;  
        res.setHeader('Content-Type', 'text/plain');  
        res.end('Hello World');  
    }  
    const server = http.createServer(onRequest);  
    function onStartup() {  
        console.log(`Server running at http://${hostname}:${port}/`);  
    }  
    server.listen(port, hostname, onStartup);
    

    通过命令启动服务:

    $ node index.js
    Server running at http://127.0.0.1:3000/
    

    浏览器中访问http://localhost:3000,可以看到页面输出“Hello World”。
    Node.js作为一个异步事件驱动的 JavaScript 运行时,在这个 “Hello World” 示例中,可以并发处理许多连接,每一个连接都会触发一个回调,而当没有可做的事情时,Node.js 就会进入休眠状态。
    这与当今比较常见的采用操作系统线程的并发模型形成了鲜明对比。基于线程的网络效率相对较低且更难以使用。此外,由于没有锁,Node.js 的用户不用担心进程死锁的问题。Node.js 中几乎没有函数直接执行 I/O 操作(除非你使用 Node.js 标准库中的同步函数版本),其进程从不会被阻塞,因此用 Node.js 来开发可扩展系统是非常合理的。
    Node.js 在设计上类似于 Ruby 的 Event Machine 或 Python 的 Twisted 之类的系统。但 Node.js 更深入地考虑了事件模型,它将事件循环作为一个运行时结构而不是作为一个库来呈现。在其他系统中,总是有一个阻塞调用来启动事件循环。通常情况下,要执行的行为是通过脚本开始时的回调来定义的,然后通过 EventMachine::run() 这样的阻塞调用来启动服务器。而在 Node.js 中,没有这种启动事件循环的调用。Node.js 在执行输入脚本后直接进入事件循环,当没有更多的回调要执行时,Node.js 就会退出事件循环。这种行为就像浏览器的 JavaScript 一样 —— 事件循环对用户是隐藏的。
    HTTP 是 Node.js 中的一等公民,设计时考虑到了流式和低延迟,这使得 Node.js 非常适合作为网络库或框架的基础。
    Node.js 被设计成单线程运行,但这并不意味着你无法利用到 CPU 的多个核心。你可以通过 child_process.fork() API 来生成子进程,并且它被设计成非常易于通信。而建立在同一个接口之上的 cluster 模块允许你在进程之间共享套接字(sockets),以实现核心的负载均衡。

    3、Node.js图片上传示例

    在这个例子中,设计了简单的文根处理模块,同时为每一个文根设计了单独的请求处理模块,实现了简单的图片上传和显示功能,通过这个例子,可以了解Node.js的模块组织形式。
    这个例子中用到一个外部模块依赖formidable,需要通过如下命令安装:

    npm install formidable
    

    在一个空目录中,依次新建如下文件。
    index.js

    var server = require("./server");  
    var router = require("./router");  
    var requestHandlers = require("./requestHandlers");  
    var handle = {};  
    handle["/"] = requestHandlers.start;  
    handle["/start"] = requestHandlers.start;  
    handle["/upload"] = requestHandlers.upload;  
    handle["/show"] = requestHandlers.show;  
    server.start(router.route, handle);
    

    server.js

    var http = require("http");  
    var url = require("url");  
    function start(route, handle) {  
        function onRequest(request, response) {  
            var pathname = url.parse(request.url).pathname;  
            console.log("Request for " + pathname + " received.");  
            route(handle, pathname, response, request);  
        }  
        http.createServer(onRequest).listen(8888);  
        console.log("Server has started.");  
    }  
    exports.start = start;
    

    router.js

    function route(handle, pathname, response, postData) {  
        console.log("About to route a request for " + pathname);  
        if (typeof handle[pathname] === 'function') {  
            handle[pathname](response, postData);  
        } else {  
            console.log("No request handler found for " + pathname);  
            response.writeHead(404, {"Content-Type": "text/plain"});  
            response.write("404 Not found");  
            response.end();  
        }  
    }  
    exports.route = route;
    

    requestHandlers.js

    var querystring = require("querystring"),  
        fs = require("fs"),  
        formidable = require("formidable");  
    function start(response) {  
        console.log("Request handler 'start' was called.");  
        var body = '<html>'+  
            '<head>'+  
            '<meta http-equiv="Content-Type" content="text/html; '+  
            'charset=UTF-8" />'+  
            '</head>'+  
            '<body>' +  
        '<form action="/upload" enctype="multipart/form-data" '+  
        'method="post">'+  
        '<input type="file" name="upload" multiple="multiple">'+  
        '<input type="submit" value="Upload file" />'+  
        '</form>'+  
        '</body>'+  
        '</html>';  
        response.writeHead(200, {"Content-Type": "text/html"});  
        response.write(body);  
        response.end();  
    }  
    function upload(response, request) {  
        console.log("Request handler 'upload' was called.");  
        var form = new formidable.IncomingForm();  
        console.log("about to parse");  
        form.parse(request, function(error, fields, files) {  
            console.log("parsing done");  
            fs.renameSync(files.upload.filepath, "test.png");  
            response.writeHead(200, {"Content-Type": "text/html"});  
            response.write("received image:<br/>");  
            response.write("<img src='/show' />");  
            response.end();  
        });  
    }  
    function show(response) {  
        console.log("Request handler 'show' was called.");  
        fs.readFile("test.png", "binary", function(error, file) {  
            if(error) {  
                response.writeHead(500, {"Content-Type": "text/plain"});  
                response.write(error + "\n");  
                response.end();  
            } else {  
                response.writeHead(200, {"Content-Type": "image/png"});  
                response.write(file, "binary");  
                response.end();  
            }  
        });  
    }  
    exports.start = start;  
    exports.upload = upload;  
    exports.show = show;
    

    在该目录下通过如下命令启动服务:

    $ node index.js
    Server has started.
    

    在浏览器中访问http://localhost:8888/start

    upload page

    选中图片上传之后,效果如下:


    upload result

    参考资料

    相关文章

      网友评论

          本文标题:NodeJS入门

          本文链接:https://www.haomeiwen.com/subject/laymtdtx.html