精华内容
下载资源
问答
  • Node.js 教程

    2021-03-30 10:01:58
    Node.js 教程 nodejs 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。 Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎...

    Node.js 教程

    nodejs 简单的说 Node.js 就是运行在服务端的 JavaScript。

    Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。

    Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。


    谁适合阅读本教程?
    如果你是一个前端程序员,你不懂的像PHP、Python或Java等动态编程语言,然后你想创建自己的服务,那么Node.js是一个非常好的选择。

    Node.js 是运行在服务端的 JavaScript,如果你熟悉Javascript,那么你将会很容易的学会Node.js。

    当然,如果你是后端程序员,想部署一些高性能的服务,那么学习Node.js也是一个非常好的选择。


    学习本教程前你需要了解
    在继续本教程之前,你应该了解一些基本的计算机编程术语。如果你学习过Javascript,PHP,Java等编程语言,将有助于你更快的了解Node.js编程。


    第一个Node.js程序:Hello World!
    以下是我们的第一个Node.js程序:

    console.log("Hello World");
    

    保存该文件,并通过 Node.js 来执行:

    node helloworld.js程序执行后,正常的话,就会在终端输出 Hello World。

    Node.js 创建HTTP服务器

    如果我们使用PHP来编写后端的代码时,需要Apache 或者 Nginx 的HTTP 服务器,并配上 mod_php5 模块和php-cgi。

    从这个角度看,整个"接收 HTTP 请求并提供 Web 页面"的需求根本不需 要 PHP 来处理。

    不过对 Node.js 来说,概念完全不一样了。使用 Node.js 时,我们不仅仅 在实现一个应用,同时还实现了整个 HTTP 服务器。事实上,我们的 Web 应用以及对应的 Web 服务器基本上是一样的。


    基础的 HTTP 服务器
    在你的项目的根目录下创建一个叫 server.js 的文件,并写入以下代码:

    var http = require('http');
    
    http.createServer(function (request, response) {
      response.writeHead(200, {'Content-Type': 'text/plain'});
      response.end('Hello World\n');
    }).listen(8888);
    

    console.log(‘Server running at http://127.0.0.1:8888/’);
    以上代码我们完成了一个可以工作的 HTTP 服务器。

    使用 node命令 执行以上的代码:

    node server.js
    Server running at http://127.0.0.1:8888/
    

    接下来,打开浏览器访问 http://127.0.0.1:8888/,你会看到一个写着 "Hello World"的网页。

    分析Node.js 的 HTTP 服务器:

    第一行请求(require)Node.js 自带的 http 模块,并且把它赋值给 http 变量。
    接下来我们调用 http 模块提供的函数: createServer 。这个函数会返回 一个对象,这个对象有一个叫做 listen 的方法,这个方法有一个数值参数, 指定这个 HTTP 服务器监听的端口号。

    Node.js模块系统

    为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。

    模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。

    创建模块
    在 Node.js 中,创建一个模块非常简单,如下我们创建一个 ‘main.js’ 文件,代码如下:

    var hello = require('./hello');
    hello.world();
    

    以上实例中,代码 require(’./hello’) 引入了当前目录下的hello.js文件(./ 为当前目录,node.js默认后缀为js)。

    Node.js 提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

    接下来我们就来创建hello.js文件,代码如下:

    exports.world = function() {
      console.log('Hello World');
    }
    

    在以上示例中,hello.js 通过 exports 对象把 world 作为模块的访 问接口,在 main.js 中通过 require(’./hello’) 加载这个模块,然后就可以直接访 问main.js 中 exports 对象的成员函数了。

    有时候我们只是想把一个对象封装到模块中,格式如下:

    module.exports = function() {
      // ...
    }
    

    例如:

    //hello.js 
    function Hello() { 
    	varname; 
    	this.setName = function(thyName) { 
    		name = thyName; 
    	}; 
    	this.sayHello = function() { 
    		console.log('Hello ' + name); 
    	}; 
    }; 
    module.exports = Hello;
    

    这样就可以直接获得这个对象了:

    
    ```clike
    //main.js 
    var Hello = require('./hello'); 
    hello = new Hello(); 
    hello.setName('BYVoid'); 
    hello.sayHello(); 
    
    
    模块接口的唯一变化是使用 module.exports = Hello 代替了exports.world = function(){}。 在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。 
    
    
    --------------------------------------------------------------------------------
    
    服务端的模块放在哪里
    也许你已经注意到,我们已经在代码中使用了模块了。像这样:
    
    ```clike
    var http = require("http");
    
    ...
    
    http.createServer(...);
    

    Node.js中自带了一个叫做"http"的模块,我们在我们的代码中请求它并把返回值赋给一个本地变量。

    这把我们的本地变量变成了一个拥有所有 http 模块所提供的公共方法的对象。

    Node.js 的 require方法中的文件查找策略如下:

    由于Node.js中存在4类模块(原生模块和3种文件模块),尽管require方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同。如下图所示:

    从文件模块缓存中加载
    尽管原生模块与文件模块的优先级不同,但是都不会优先于从文件模块的缓存中加载已经存在的模块。

    从原生模块加载

    原生模块的优先级仅次于文件模块缓存的优先级。require方法在解析文件名之后,优先检查模块是否在原生模块列表中。以http模块为例,尽管在目录下存在一个http/http.js/http.node/http.json文件,require(“http”)都不会从这些文件中加载,而是从原生模块中加载。

    原生模块也有一个缓存区,同样也是优先从缓存区加载。如果缓存区没有被加载过,则调用原生模块的加载方式进行加载和执行。

    从文件加载
    当文件模块缓存中不存在,而且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件,加载过程中的包装和编译细节在前一节中已经介绍过,这里我们将详细描述查找文件模块的过程,其中,也有一些细节值得知晓。

    require方法接受以下几种参数的传递:

    1. http、fs、path等,原生模块。

    2. ./mod或…/mod,相对路径的文件模块。

    3. /pathtomodule/mod,绝对路径的文件模块。

    4. mod,非原生模块的文件模块。

    Node.js 事件

    Node.js 所有的异步I/O 操作在完成时都会发送一个事件到事件队列。

    Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStream对象会在文件被打开的时候发出一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。 你可以通过require(“events”);来访问该模块。

    下面我们用一个简单的例子说明 EventEmitter 的用法:

    //event.js 
    var EventEmitter = require('events').EventEmitter; 
    var event = new EventEmitter(); 
    event.on('some_event', function() { 
    	console.log('some_event occured.'); 
    }); 
    setTimeout(function() { 
    	event.emit('some_event'); 
    }, 1000); 
    

    运行这段代码,1秒后控制台输出了 ‘some_event occured’。其原理是 event 对象 注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在1000毫秒以后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。


    EventEmitter介绍
    events 模块只提供了一个对象: events.EventEmitter。EventEmitter 的核心就 是事件发射与事件监听器功能的封装。

    EventEmitter 的每个事件由一个事件名和若干个参 数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持 若干个事件监听器。

    当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作 为回调函数参数传递。

    让我们以下面的例子解释这个过程:

    var events = require('events'); 
    var emitter = new events.EventEmitter(); 
    emitter.on('someEvent', function(arg1, arg2) { 
    	console.log('listener1', arg1, arg2); 
    }); 
    emitter.on('someEvent', function(arg1, arg2) { 
    	console.log('listener2', arg1, arg2); 
    }); 
    emitter.emit('someEvent', 'byvoid', 1991); 
    

    运行的结果是:

    listener1 byvoid 1991 
    listener2 byvoid 1991 
    

    以上例子中,emitter 为事件 someEvent 注册了两个事件监听器,然后发射了 someEvent 事件。运行结果中可以看到两个事件监听器回调函数被先后调用。 这就是EventEmitter最简单的用法。

    EventEmitter常用的API
    EventEmitter.on(event, listener)、emitter.addListener(event, listener) 为指定事件注册一个监听器,接受一个字 符串 event 和一个回调函数 listener。

    server.on('connection', function (stream) {
      console.log('someone connected!');
    });
    

    EventEmitter.emit(event, [arg1], [arg2], […]) 发射 event 事件,传 递若干可选参数到事件监听器的参数表。

    EventEmitter.once(event, listener) 为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。

    server.once('connection', function (stream) {
      console.log('Ah, we have our first user!');
    });
    

    EventEmitter.removeListener(event, listener) 移除指定事件的某个监听 器,listener 必须是该事件已经注册过的监听器。

    var callback = function(stream) {
      console.log('someone connected!');
    };
    server.on('connection', callback);
    // ...
    server.removeListener('connection', callback);
    

    EventEmitter.removeAllListeners([event]) 移除所有事件的所有监听器, 如果指定 event,则移除指定事件的所有监听器。


    error 事件
    EventEmitter 定义了一个特殊的事件 error,它包含了"错误"的语义,我们在遇到 异常的时候通常会发射 error 事件。

    当 error 被发射时,EventEmitter 规定如果没有响 应的监听器,Node.js 会把它当作异常,退出程序并打印调用栈。

    我们一般要为会发射 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。例如:

    var events = require('events'); 
    var emitter = newevents.EventEmitter(); 
    emitter.emit('error'); 
    

    运行时会显示以下错误:

    node.js:201 
    throw e; // process.nextTick error, or 'error' event on first tick 
    ^ 
    Error: Uncaught, unspecified 'error' event. 
    at EventEmitter.emit (events.js:50:15) 
    at Object.<anonymous> (/home/byvoid/error.js:5:9) 
    at Module._compile (module.js:441:26) 
    at Object..js (module.js:459:10) 
    at Module.load (module.js:348:31) 
    at Function._load (module.js:308:12) 
    at Array.0 (module.js:479:10) 
    at EventEmitter._tickCallback (node.js:192:40) 
    

    继承 EventEmitter
    大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。

    为什么要这样做呢?原因有两点:

    首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发射应该是一个对象的方法。

    其次JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。

    Node.js 函数

    在JavaScript中,一个函数可以作为另一个函数接收一个参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。

    Node.js中函数的使用与Javascript类似,举例来说,你可以这样做:

    function say(word) {
      console.log(word);
    }
    
    function execute(someFunction, value) {
      someFunction(value);
    }
    
    execute(say, "Hello");
    

    以上代码中,我们把 say 函数作为execute函数的第一个变量进行了传递。这里返回的不是 say 的返回值,而是 say 本身!

    这样一来, say 就变成了execute 中的本地变量 someFunction ,execute可以通过调用 someFunction() (带括号的形式)来使用 say 函数。

    当然,因为 say 有一个变量, execute 在调用 someFunction 时可以传递这样一个变量。


    匿名函数
    我们可以把一个函数作为变量传递。但是我们不一定要绕这个"先定义,再传递"的圈子,我们可以直接在另一个函数的括号中定义和传递这个函数:

    function execute(someFunction, value) {
      someFunction(value);
    }
    
    execute(function(word){ console.log(word) }, "Hello");
    

    我们在 execute 接受第一个参数的地方直接定义了我们准备传递给 execute 的函数。

    用这种方式,我们甚至不用给这个函数起名字,这也是为什么它被叫做匿名函数 。


    函数传递是如何让HTTP服务器工作的
    带着这些知识,我们再来看看我们简约而不简单的HTTP服务器:

    var http = require("http");
    
    http.createServer(function(request, response) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.write("Hello World");
      response.end();
    }).listen(8888);
    

    现在它看上去应该清晰了很多:我们向 createServer 函数传递了一个匿名函数。

    用这样的代码也可以达到同样的目的:

    var http = require("http");
    
    function onRequest(request, response) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.write("Hello World");
      response.end();
    }
    
    http.createServer(onRequest).listen(8888);
    

    Node.js 路由

    我们要为路由提供请求的URL和其他需要的GET及POST参数,随后路由需要根据这些数据来执行相应的代码。

    因此,我们需要查看HTTP请求,从中提取出请求的URL以及GET/POST参数。这一功能应当属于路由还是服务器(甚至作为一个模块自身的功能)确实值得探讨,但这里暂定其为我们的HTTP服务器的功能。

    我们需要的所有数据都会包含在request对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,它们分别是url和querystring模块。

                       url.parse(string).query
                                               |
               url.parse(string).pathname      |
                           |                   |
                           |                   |
                         ------ -------------------
    
    http://localhost:8888/start?foo=bar&hello=world
    
                                    ---       -----
                                     |          |
                                     |          |
                  querystring(string)["foo"]    |
                                                |
                             querystring(string)["hello"]
    

    当然我们也可以用querystring模块来解析POST请求体中的参数,稍后会有演示。

    现在我们来给onRequest()函数加上一些逻辑,用来找出浏览器请求的URL路径:

    var http = require("http");
    var url = require("url");
    
    function start() {
      function onRequest(request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
      }
    
      http.createServer(onRequest).listen(8888);
      console.log("Server has started.");
    }
    
    exports.start = start;
    

    好了,我们的应用现在可以通过请求的URL路径来区别不同请求了–这使我们得以使用路由(还未完成)来将请求以URL路径为基准映射到处理程序上。

    在我们所要构建的应用中,这意味着来自/start和/upload的请求可以使用不同的代码来处理。稍后我们将看到这些内容是如何整合到一起的。

    现在我们可以来编写路由了,建立一个名为router.js的文件,添加以下内容:

    function route(pathname) {
      console.log("About to route a request for " + pathname);
    }
    
    exports.route = route;
    

    如你所见,这段代码什么也没干,不过对于现在来说这是应该的。在添加更多的逻辑以前,我们先来看看如何把路由和服务器整合起来。

    我们的服务器应当知道路由的存在并加以有效利用。我们当然可以通过硬编码的方式将这一依赖项绑定到服务器上,但是其它语言的编程经验告诉我们这会是一件非常痛苦的事,因此我们将使用依赖注入的方式较松散地添加路由模块。

    首先,我们来扩展一下服务器的start()函数,以便将路由函数作为参数传递过去:

    var http = require("http");
    var url = require("url");
    
    function start(route) {
      function onRequest(request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");
    
        route(pathname);
    
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
      }
    
      http.createServer(onRequest).listen(8888);
      console.log("Server has started.");
    }
    
    exports.start = start;
    

    同时,我们会相应扩展index.js,使得路由函数可以被注入到服务器中:

    var server = require("./server");
    var router = require("./router");
    
    server.start(router.route);
    

    在这里,我们传递的函数依旧什么也没做。

    如果现在启动应用(node index.js,始终记得这个命令行),随后请求一个URL,你将会看到应用输出相应的信息,这表明我们的HTTP服务器已经在使用路由模块了,并会将请求的路径传递给路由:

    bash$ node index.js
    Request for /foo received.
    About to route a request for /foo
    

    以上输出已经去掉了比较烦人的/favicon.ico请求相关的部分。

    Node.js 全局对象

    JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可 以在程序的任何地方访问,即全局变量。

    在浏览器JavaScript 中,通常window 是全局对象, 而Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。

    我们在Node.js 中能够直接访问到对象通常都是 global 的属性,如 console、process 等,下面逐一介绍。


    全局对象与全局变量
    global 最根本的作用是作为全局变量的宿主。按照ECMAScript 的定义,满足以下条 件的变量是全局变量:

    在最外层定义的变量;
    全局对象的属性;
    隐式定义的变量(未定义直接赋值的变量)。
    当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。需要注 意的是,在Node.js 中你不可能在最外层定义变量,因为所有用户代码都是属于当前模块的, 而模块本身不是最外层上下文。

    注意: 永远使用var 定义变量以避免引入全局变量,因为全局变量会污染 命名空间,提高代码的耦合风险。


    process
    process 是一个全局变量,即 global 对象的属性。

    它用于描述当前Node.js 进程状态 的对象,提供了一个与操作系统的简单接口。通常在你写本地命令行程序的时候,少不了要 和它打交道。下面将会介绍process 对象的一些最常用的成员方法。

    process.argv是命令行参数数组,第一个元素是 node,第二个元素是脚本文件名, 从第三个元素开始每个元素是一个运行参数。

    console.log(process.argv); 
    

    将以上代码存储为argv.js,通过以下命令运行:

    $ node argv.js 1991 name=byvoid --v "Carbo Kuo" 
    [ 'node', 
    '/home/byvoid/argv.js', 
    '1991', 
    'name=byvoid', 
    '--v', 
    'Carbo Kuo' ]
    

    process.stdout是标准输出流,通常我们使用的 console.log() 向标准输出打印 字符,而 process.stdout.write() 函数提供了更底层的接口。
    process.stdin是标准输入流,初始时它是被暂停的,要想从标准输入读取数据, 你必须恢复流,并手动编写流的事件响应函数。

    process.stdin.resume(); 
    process.stdin.on('data', function(data) { 
    process.stdout.write('read from console: ' + data.toString()); 
    }); 
    

    process.nextTick(callback)的功能是为事件循环设置一项任务,Node.js 会在 下次事件循环调响应时调用 callback。
    初学者很可能不理解这个函数的作用,有什么任务不能在当下执行完,需要交给下次事 件循环响应来做呢?

    我们讨论过,Node.js 适合I/O 密集型的应用,而不是计算密集型的应用, 因为一个Node.js 进程只有一个线程,因此在任何时刻都只有一个事件在执行。

    如果这个事 件占用大量的CPU 时间,执行事件循环中的下一个事件就需要等待很久,因此Node.js 的一 个编程原则就是尽量缩短每个事件的执行时间。process.nextTick() 提供了一个这样的 工具,可以把复杂的工作拆散,变成一个个较小的事件。

    functiondoSomething(args, callback) { 
    	somethingComplicated(args); 
    	callback(); 
    } 
    doSomething(functiononEnd() { 
    	compute(); 
    }); 
    

    我们假设compute() 和somethingComplicated() 是两个较为耗时的函数,以上 的程序在调用 doSomething() 时会先执行somethingComplicated(),然后立即调用 回调函数,在 onEnd() 中又会执行 compute()。下面用process.nextTick() 改写上 面的程序:

    functiondoSomething(args, callback) { 
    	somethingComplicated(args); 
    	process.nextTick(callback); 
    } 
    doSomething(functiononEnd() { 
    	compute(); 
    }); 
    

    改写后的程序会把上面耗时的操作拆分为两个事件,减少每个事件的执行时间,提高事 件响应速度。

    注意: 不要使用setTimeout(fn,0)代替process.nextTick(callback), 前者比后者效率要低得多。

    我们探讨了process对象常用的几个成员,除此之外process还展示了process.platform、 process.pid、process.execPath、process.memoryUsage() 等方法,以及POSIX 进程信号响应机制。有兴趣的读者可以访问http://nodejs.org/api/process.html 了解详细 内容。


    console 用于提供控制台标准输出,它是由Internet Explorer 的JScript 引擎提供的调试 工具,后来逐渐成为浏览器的事实标准。

    Node.js 沿用了这个标准,提供与习惯行为一致的 console 对象,用于向标准输出流(stdout)或标准错误流(stderr)输出字符。 ? console.log():向标准输出流打印字符并以换行符结束。

    console.log 接受若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。

    第一个参数是一个字符串,如果没有 参数,只打印一个换行。

    console.log('Hello world'); 
    console.log('byvoid%diovyb'); 
    console.log('byvoid%diovyb', 1991); 
    

    运行结果为:

    Hello world 
    byvoid%diovyb 
    byvoid1991iovyb 
    

    console.error():与console.log() 用法相同,只是向标准错误流输出。
    console.trace():向标准错误流输出当前的调用栈。
    console.trace();
    运行结果为:

    Trace: 
    at Object.<anonymous> (/home/byvoid/consoletrace.js:1:71) 
    at Module._compile (module.js:441:26) 
    at Object..js (module.js:459:10) 
    at Module.load (module.js:348:31) 
    at Function._load (module.js:308:12) 
    at Array.0 (module.js:479:10) 
    at EventEmitter._tickCallback (node.js:192:40)
    

    Node.js 常用工具 util

    util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足。


    util.inherits
    util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数。

    JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有 提供对象继承的语言级别特性,而是通过原型复制来实现的。

    在这里我们只介绍util.inherits 的用法,示例如下:

    varutil = require('util'); 
    functionBase() { 
    	this.name = 'base'; 
    	this.base = 1991; 
    	this.sayHello = function() { 
    	console.log('Hello ' + this.name); 
    	}; 
    } 
    Base.prototype.showName = function() { 
    	console.log(this.name);
    }; 
    functionSub() { 
    	this.name = 'sub'; 
    } 
    util.inherits(Sub, Base); 
    varobjBase = newBase(); 
    objBase.showName(); 
    objBase.sayHello(); 
    console.log(objBase); 
    varobjSub = newSub(); 
    objSub.showName(); 
    //objSub.sayHello(); 
    console.log(objSub); 
    

    我们定义了一个基础对象Base 和一个继承自Base 的Sub,Base 有三个在构造函数 内定义的属性和一个原型中定义的函数,通过util.inherits 实现继承。运行结果如下:

    base 
    Hello base 
    { name: 'base', base: 1991, sayHello: [Function] } 
    sub 
    { name: 'sub' }
    

    注意:Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承。

    同时,在原型中定义的属性不会被console.log 作 为对象的属性输出。如果我们去掉 objSub.sayHello(); 这行的注释,将会看到:

    node.js:201 
    throw e; // process.nextTick error, or 'error' event on first tick 
    ^ 
    TypeError: Object #<Sub> has no method 'sayHello' 
    at Object.<anonymous> (/home/byvoid/utilinherits.js:29:8) 
    at Module._compile (module.js:441:26) 
    at Object..js (module.js:459:10) 
    at Module.load (module.js:348:31) 
    at Function._load (module.js:308:12) 
    at Array.0 (module.js:479:10) 
    at EventEmitter._tickCallback (node.js:192:40) 
    

    util.inspect
    util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象。

    showHidden 是一个可选参数,如果值为 true,将会输出更多隐藏信息。

    depth 表示最大递归的层数,如果对象很复杂,你可以指定层数以控制输出信息的多 少。如果不指定depth,默认会递归2层,指定为 null 表示将不限递归层数完整遍历对象。 如果color 值为 true,输出格式将会以ANSI 颜色编码,通常用于在终端显示更漂亮 的效果。

    特别要指出的是,util.inspect 并不会简单地直接把对象转换为字符串,即使该对 象定义了toString 方法也不会调用。

    varutil = require('util'); 
    functionPerson() { 
    	this.name = 'byvoid'; 
    	this.toString = function() { 
    	return this.name; 
    	}; 
    } 
    varobj = newPerson(); 
    console.log(util.inspect(obj)); 
    console.log(util.inspect(obj, true)); 
    运行结果是: 
    
    { name: 'byvoid', toString: [Function] } 
    { toString: 
    { [Function] 
    [prototype]: { [constructor]: [Circular] }, 
    [caller]: null, 
    [length]: 0, 
    [name]: '', 
    [arguments]: null }, 
    name: 'byvoid' } 
    

    util.isArray(object)
    如果给定的参数 “object” 是一个数组返回true,否则返回false。

    var util = require('util');
    
    util.isArray([])
      // true
    util.isArray(new Array)
      // true
    util.isArray({})
      // false
    

    util.isRegExp(object)
    如果给定的参数 “object” 是一个正则表达式返回true,否则返回false。

    var util = require('util');
    
    util.isRegExp(/some regexp/)
      // true
    util.isRegExp(new RegExp('another regexp'))
      // true
    util.isRegExp({})
      // false
    

    util.isDate(object)
    如果给定的参数 “object” 是一个日期返回true,否则返回false。

    var util = require('util');
    
    util.isDate(new Date())
      // true
    util.isDate(Date())
      // false (without 'new' returns a String)
    util.isDate({})
      // false
    

    util.isError(object)
    如果给定的参数 “object” 是一个错误对象返回true,否则返回false。

    var util = require('util');
    
    util.isError(new Error())
      // true
    util.isError(new TypeError())
      // true
    util.isError({ name: 'Error', message: 'an error occurred' })
      // false
    

    Node.js 文件系统

    Node.js 文件系统封装在 fs 模块是中,它提供了文件的读取、写入、更名、删除、遍历目录、链接等POSIX 文件系统操作。

    与其他模块不同的是,fs 模块中所有的操作都提供了异步的和 同步的两个版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。我们以几个函数为代表,介绍 fs 常用的功能,并列出 fs 所有函数 的定义和功能。


    fs.readFile
    Node.js读取文件函数语法如下:

    fs.readFile(filename,[encoding],[callback(err,data)])
    

    filename(必选),表示要读取的文件名。
    encoding(可选),表示文件的字符编码。
    callback 是回调函数,用于接收文件的内容。
    如果不指 定 encoding,则 callback 就是第二个参数。回调函数提供两个参数 err 和 data,err 表 示有没有错误发生,data 是文件内容。如果指定了 encoding,data 是一个解析后的字符 串,否则 data 将会是以 Buffer 形式表示的二进制数据。

    例如以下程序,我们从content.txt 中读取数据,但不指定编码:

    varfs = require('fs'); 
    fs.readFile('content.txt', function(err, data) { 
    	if(err) { 
    		console.error(err); 
    	} else{ 
    		console.log(data); 
    	} 
    }); 
    

    假设content.txt 中的内容是UTF-8 编码的 Text 文本文件示例,运行结果如下:

    <Buffer 54 65 78 74 20 e6 96 87 e6 9c ac e6 96 87 e4 bb b6 e7 a4 ba e4 be 8b>
    这个程序以二进制的模式读取了文件的内容,data 的值是 Buffer 对象。如果我们给

    fs.readFile 的 encoding 指定编码:

    var fs = require('fs'); 
    	fs.readFile('content.txt', 'utf-8', function(err, data) { 
    	if (err) { 
    		console.error(err); 
    	} else { 
    		console.log(data); 
    	} 
    }); 
    

    那么运行结果则是:

    Text 文本文件示例
    当读取文件出现错误时,err 将会是 Error 对象。如果content.txt 不存在,运行前面 的代码则会出现以下结果:

    { [Error: ENOENT, no such file or directory 'content.txt'] errno: 34, code: 'ENOENT', 
    path: 'content.txt' } 
    

    fs.readFileSync
    fs.readFileSync(filename, [encoding])是 fs.readFile 同步的版本。它接受 的参数和 fs.readFile 相同,而读取到的文件内容会以函数返回值的形式返回。如果有错 误发生,fs 将会抛出异常,你需要使用 try 和 catch 捕捉并处理异常。

    注意:与同步I/O 函数不同,Node.js 中异步函数大多没有返回值。


    fs.open
    fs.open(path, flags, [mode], [callback(err, fd)])是POSIX open 函数的 封装,与C 语言标准库中的 fopen 函数类似。它接受两个必选参数,path 为文件的路径, flags 可以是以下值。

    r :以读取模式打开文件。
    r+ :以读写模式打开文件。
    w :以写入模式打开文件,如果文件不存在则创建。
    w+ :以读写模式打开文件,如果文件不存在则创建。
    a :以追加模式打开文件,如果文件不存在则创建。
    a+ :以读取追加模式打开文件,如果文件不存在则创建


    fs.read
    fs.read语法格式如下:

    fs.read(fd, buffer, offset, length, position, [callback(err, bytesRead, buffer)])
    参数说明:

    fd: 读取数据并写入 buffer 指向的缓冲区对象。
    offset: 是buffer 的写入偏移量。
    length: 是要从文件中读取的字节数。
    position: 是文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
    callback:回调函数传递bytesRead 和 buffer,分别表示读取的字节数和缓冲区对象。
    以下是一个使用 fs.open 和 fs.read 的示例。

    varfs = require('fs'); 
    fs.open('content.txt', 'r', function(err, fd) { 
    	if(err) { 
    		console.error(err); 
    		return; 
    	} 
    	varbuf = newBuffer(8); 
    	fs.read(fd, buf, 0, 8, null, function(err, bytesRead, buffer) { 
    		if(err) { 
    			console.error(err); 
    			return; 
    		} 
    		console.log('bytesRead: ' + bytesRead); 
    		console.log(buffer); 
    	}) 
    }); 
    

    运行结果是:

    bytesRead: 8 
    <Buffer 54 65 78 74 20 e6 96 87> 
    

    一般来说,除非必要,否则不要使用这种方式读取文件,因为它要求你手动管理缓冲区 和文件指针,尤其是在你不知道文件大小的时候,这将会是一件很麻烦的事情。


    Node.js GET/POST请求

    在很多场景中,我们的服务器都需要跟用户的浏览器打交道,如表单提交。

    表单提交到服务器一般都使用GET/POST请求。

    本章节我们将为大家介绍 Node.js GET/POST请求。


    获取GET请求内容
    由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET请求的参数。

    node.js中url模块中的parse函数提供了这个功能。

    var http = require('http');
    var url = require('url');
    var util = require('util');
    
    http.createServer(function(req, res){
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end(util.inspect(url.parse(req.url, true)));
    }).listen(3000);
    

    在浏览器中访问http://localhost:3000/user?name=w3c&email=w3c@w3cschool.cc 然后查看返回结果:

    w3cnodejs


    获取POST请求内容
    POST请求的内容全部的都在请求体中,http.ServerRequest并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。

    比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所有node.js默认是不会解析请求体的, 当你需要的时候,需要手动来做。

    var http = require('http');
    var querystring = require('querystring');
    var util = require('util');
    
    http.createServer(function(req, res){
        var post = '';     //定义了一个post变量,用于暂存请求体的信息
    
        req.on('data', function(chunk){    //通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
            post += chunk;
        });
    
        req.on('end', function(){    //在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
            post = querystring.parse(post);
            res.end(util.inspect(post));
        });
    }).listen(3000);
    
    展开全文
  • node.js教程

    2015-08-28 11:17:26
    node.js 详细教程 node.js帮助文档 node.js api,node.js开发必备,教程经典
  • Node.js教程

    2019-07-10 10:32:07
    Node.js教程 简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行...

    Node.js 教程

    nodejs

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

    谁适合阅读本教程?

    如果你是一个前端程序员,你不懂得像PHP、Python或Ruby等动态编程语言,然后你想创建自己的服务,那么Node.js是一个非常好的选择。

    Node.js 是运行在服务端的 JavaScript,如果你熟悉Javascript,那么你将会很容易的学会Node.js。

    当然,如果你是后端程序员,想部署一些高性能的服务,那么学习Node.js也是一个非常好的选择。

    学习本教程前你需要了解

    在继续本教程之前,你应该了解一些基本的计算机编程术语。如果你学习过Javascript,PHP,Java等编程语言,将有助于你更快的了解Node.js编程。

    使用的版本

    我们可以使用以下命令来查看当前的 Node 版本:

    $ node -v
    v4.4.3

    注意:不同版本间可能是有差异的。

    第一个Node.js程序:Hello World!

    脚本模式

    以下是我们的第一个Node.js程序:

    console.log("Hello World");

    保存该文件,文件名为 helloworld.js, 并通过 node命令来执行:

    node helloworld.js

    程序执行后,正常的话,就会在终端输出 Hello World。

    交互模式

    打开终端,键入node进入命令交互模式,可以输入一条代码语句后立即执行并显示结果,例如:

    $ node
    > console.log('Hello World!');
    Hello World!

    Gif 实例演示

    接下来我们通过 Gif 图为大家演示实例操作:

     

    展开全文
  • 本篇教程介绍了Node.js教程 基于thrift的Node.js rpc服务,希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。<1.在node.js服务下创建node_modules文件,npminstallthrift下载thrift到该文件...

    本篇教程介绍了Node.js教程 基于thrift的Node.js rpc服务,希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。

    <

    1.在node.js 服务下创建node_modules文件,npm install  thrift 下载thrift到该文件下。

    2.编写idl文件。user.thrift 内容如下:

    struct User{

    1: string uid,

    2: string uname,

    3: bool usex,

    4: i16 uage,

    }

    service UserService{

    void add(1: User u),

    User get(1: string uid),

    }

    3.生成代码:

    运行:thrift   --gen js:node user.thrift

    会在当前目录下生成一个gen -nodejs文件夹,里面就是我们需要的js代码,将js代码拷贝到我们的项目中。

    4.创建node.js服务段和客户端

    服务端:

    var thrift = require(‘thrift‘);

    var UserService = require(‘./gen-nodejs/UserService.js‘),

    ttypes = require(‘./gen-nodejs/user_types‘);

    var users = {};

    var server = thrift.createServer(UserService, {

    add: function(user, callback) {

    console.log("server stored:", user.uname);

    users[user.uid] = user;

    callback();

    }

    });

    server.listen(7911);

    console.log(‘server start‘);

    客户端:

    var thrift = require(‘thrift‘);

    var UserStorage = require(‘./gen-nodejs/UserStorage.js‘),

    ttypes = require(‘./gen-nodejs/user_types‘);

    var connection = thrift.createConnection(‘localhost‘, 9090),

    client = thrift.createClient(UserStorage, connection);

    var user = new ttypes.UserProfile({uid: 1,

    name: "Mark Slee",

    blurb: "I‘ll find something to put here."});

    connection.on(‘error‘, function(err) {

    console.error(err);

    });

    client.store(user, function(err, response) {

    if (err) {

    console.error(err);

    } else {

    console.log("client stored:", user.uid);

    client.retrieve(user.uid, function(err, responseUser) {

    if (err) {

    console.error(err);

    } else {

    console.log("client retrieved:", responseUser.uid);

    connection.end();

    }

    });

    }

    });

    本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注WEB前端Node.js频道!

    展开全文
  • JavaScript - Node.JS教程系列 全栈开发工程师,现职于北京...

    扫码下载「CSDN程序员学院APP」,1000+技术好课免费看

    APP订阅课程,领取优惠,最少立减5元 ↓↓↓

    订阅后:请点击此处观看视频课程

     

    视频教程-JavaScript - Node.JS教程系列-Node.js

    学习有效期:永久观看

    学习时长:1241分钟

    学习计划:21天

    难度:

     

    口碑讲师带队学习,让你的问题不过夜」

    讲师姓名:李游Leo

    CEO/董事长/总经理

    讲师介绍:全栈开发工程师,现职于北京一家学院的全栈教学主任。 8年前端开发经验、4年移动端开发经验、4年UI设计经验、3年一线教学经验。 精通Node.JS、PHP、Javascript开发等多种开发技术,曾任职于时趣、百度、乐视,拥有丰富的企业级系统开发经验,长期参与一线项目开发和项目管控,对HTML5移动端互联网技术及生态体系有深刻理解。

    ☛点击立即跟老师学习☚

     

    「你将学到什么?」

    Node.JS是一套使用JavaScript语言的后台。它执行Javascript的速度非常快,性能非常好。是近几年来火的公司首选后台语言之一,同时也是前后台人员争先恐后学习的后台语言。

     

    「课程学习目录」

    第1章:Javascript - Node.JS教程系列课程预览
    1.Javascript - Node.JS教程系列课程预览
    第2章:初识Node.JS( 一 )
    1.Ajax基础部分
    2.下载安装Node.JS并使用
    3.Node.JS-GET、状态码、跨域
    第3章:初识Node.JS( 二 )
    1.Ajax的完整封装及get、post数据解析及模块
    2.Node.JS-fs模块的rename、unlink使用
    3.练习:歌单生成器
    4.练习:简易注册登陆系统
    第4章:Node.JS入门( 一 )
    1.练习:简易文章写入查看系统 - 1
    2.练习:简易文章写入查看系统 - 2
    3.node-npm包下载与上传
    第5章:Node.JS入门( 二 )
    1.练习:带注册登陆账户的文章写入查看系统 - 1
    2.练习:带注册登陆账户的文章写入查看系统 - 2
    3.练习:带注册登陆账户的文章写入查看系统 - 3
    第6章:Node.JS框架篇 - express ( 一 )
    1.express基础数据交互get、post、use
    2.express中间件、bodyparser、static模块
    第7章:Node.JS框架篇 - express ( 二 )
    1.cookie的使用
    2.Node.JS使用cookie与读取
    3.cookieparser模块的使用与cookie加密删除
    第8章:Node.JS模版篇 - jade ( 一 )
    1.jade的下载与初识
    2.jade的入门与使用
    3.练习:NodeJS的自动登陆功能的实现原理
    第9章:Node.JS模版篇 - jade ( 二 )
    1.jade的高级语法使用
    2.jade的js的快捷使用
    3.练习:jade模版的独立歌曲页面制作
    第10章:Node.JS的express进阶篇( 一 )
    1.404页面的实现原理与应用
    2.文件上传系统原理multer、path模块使用
    第11章:Node.JS的express进阶篇( 二 )
    1.express中的router路由方法的初识与作用
    2.jade模版中分页的制作
    第12章:mysql数据库的安装与使用( 一 )
    1.mysql的下载与安装
    2.navicat、SQL的SELECT、INSERT及mysql模块
    第13章:mysql数据库的安装与使用( 二 )
    1.SQL-DELETE、UPDATE、WHERE
    2.练习:jade模版文章列表路由分页的制作 - 1
    3.练习:jade模版文章列表路由分页的制作 - 2
    第14章:mysql数据库的安装与使用( 三 )
    1.基础版的网页qq的制作
    2.SQL语言-AND、OR使用
    3.数据库的导入与导出
    第15章:Node.JS练习进阶篇
    1.Ajax配合Node.JS上传任意文件系统
    2.Node.JS配合mysql文章发布、列表、查看系统

     

    7项超值权益,保障学习质量」

    • 大咖讲解

    技术专家系统讲解传授编程思路与实战。

    • 答疑服务

    专属社群随时沟通与讲师答疑,扫清学习障碍,自学编程不再难。

    • 课程资料+课件

    超实用资料,覆盖核心知识,关键编程技能,方便练习巩固。(部分讲师考虑到版权问题,暂未上传附件,敬请谅解)

    • 常用开发实战

    企业常见开发实战案例,带你掌握Python在工作中的不同运用场景。

    • 大牛技术大会视频

    2019Python开发者大会视频免费观看,送你一个近距离感受互联网大佬的机会。

    • APP+PC随时随地学习

    满足不同场景,开发编程语言系统学习需求,不受空间、地域限制。

     

    「什么样的技术人适合学习?」

    • 想进入互联网技术行业,但是面对多门编程语言不知如何选择,0基础的你
    • 掌握开发、编程技术单一、冷门,迫切希望能够转型的你
    • 想进入大厂,但是编程经验不够丰富,没有竞争力,程序员找工作难。

     

    「悉心打造精品好课,21天学到大牛3年项目经验」

    【完善的技术体系】

    技术成长循序渐进,帮助用户轻松掌握

    掌握Node.js知识,扎实编码能力

    【清晰的课程脉络】

    浓缩大牛多年经验,全方位构建出系统化的技术知识脉络,同时注重实战操作。

    【仿佛在大厂实习般的课程设计】

    课程内容全面提升技术能力,系统学习大厂技术方法论,可复用在日后工作中。

     

    「你可以收获什么?」

    本课程从零基础带你进入Node.JS的世界,真实的连续20天的真实上课视频,超过40课时的课时,每天除了新的知识点外,还包含了课件、课后作业和作业讲解。让你从无到有,从浅入深的系统的学习Node.JS。

     

    展开全文
  • Node.jsNode.js 教程

    2018-03-08 10:04:46
    Node.js 教程简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行...
  • 本篇教程介绍了Node.js教程 搭建VUE+NODE.js+ElementUI详解,希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。<1、exports和module.exportsrequire用来加载代码,而exports和module.exports...
  • Node.Js教程

    2016-09-13 17:23:47
    Node.Js视频教程Node.Js免费课程
  • 本篇教程介绍了Node.js教程 mysql模块简单实用操作,希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。<1//mysql模块简单实用操作23varmysql=require(‘mysql‘);45mc={};678vardbconfig={9...
  • node.js 教程

    2018-10-30 14:54:00
    node.js是什么 node.js是一个平台,可以再后台运行JavaScript 二 安装node.js 下载地址:官网 无脑下一步,安装完成后, 我们打开cmd控制台, 1 输入node -v 出现版本,就成功了(我发现,名字也没什么...
  • [奥莱理] PHP 开发者 Node.js 教程 (英文版) [奥莱理] Node.js for PHP Developers (E-Book) ☆ 出版信息:☆ [作者信息] Daniel Howard [出版机构] 奥莱理 [出版日期] 2012年12月14日 [图书页数] 288页 ...
  • 认识 Node.js Node 是一个服务器端 JavaScript 解释器 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效 Node.js 的包管理器 npm,是...
  • 本篇文章探讨了Node.js教程之用Node.js实现文件夹内所有文件的重命名,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。<nodeJs中我比较感兴趣的有一个地方就是fs文件系统。今天就用nodeJs...
  • UdemyNodeJS:Node.js教程
  • 最佳的 Node.js 教程结合实例 如果你正在找 Node.js 的学习资料及指南那么请继续阅读 以下是 Node.js 入门的简单介绍 如果你对 Node.js 略有了解可以直 接跳过此部分 那什么是 Node.js 呢? Node.js 是迄今运用最多的...
  • 摘要:这是一篇专门针对Node.js初学者的教程。该教程将通过具体实例,教你一步步开始Node.js之旅。 Node.js教程并不缺乏,但有大部分教程针对已有Node.js基础的开发者。“我已下载了Node.js,可我如何开始呢?...
  • Node.js教程合集(4本).zip nodejs初学者教程 nodejs教程 创建web服务 meteor开发框架
  • MySql 驱动安装定位到nodejs安装目录 cd C:\Program Files\nodejs1 node --version //查看当前版本,用于判断nodejs是否安装成功2 安装Mysql驱动:npm install mysql3 查看已安装的驱动 npm list4 查看已安装模块 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,790
精华内容 2,716
关键字:

node.js教程