Node7.7.2–explore

简介

Node是一个基于Chrome的V8JS引擎的JS运行时。Node运用事件驱动(event-driven),非阻塞I/O模型(non-blocking I/O)使其轻量和高效。Node的包管理器npm,是世界上生态系统最大的开源库。

示例

作为异步事件驱动的JS运行时,Node旨在构建大型网络应用。如下示例中,可以并发(concurrently)处理很多连接。每次连接中,回调都被触发(fired),但如果没有事做Node保持休眠。

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\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

这点与当今使用OS线程(OS threads)的更常见并发模型对比鲜明。基于线程(Thread-based)的网络相对低效且难以使用。 此外,Node的用户不必担心死锁(dead-locking)过程因为压根没有。几乎没有函数在Node中直接执行I/O 所以进程永不阻塞。因此,大规模系统在Node中可以非常合理地开发。

Node设计上类似Ruby的Event Machine或Python的Twisted等系统。Node在事件模型( event model)上更进一步。 它提供一个事件循环(event loop)而非库(library)作为运行时的构建(runtime construct)。其它系统中事件循 环启动之初经常存在阻塞的调用(blocking call)。通常行为(behavior)通过脚本起初的回调来定义,且最终通过启动一个阻塞 的回调(如EventMachine::run())启动一个服务。在Node中不存在如此的start-the-event-loop调用。Node中执行了 输入脚本便直接进入事件循环。当没有更多回调去执行时,Node存在event loop;此举正如浏览器JS—event loop对用户隐藏。

HTTP是Node中的头等公民,设计时考虑流和低延迟。这使得Node非常适合于Web库或框架的基础。

只因Node旨在无线程,并非不能利用环境中的多核。子进程可以过使用我们的child_process.fork()API生成,并且设计为 易于与之通信。基于同一接口的是集群模块,它允许您在进程之间共享套接字,以便通过内核实现负载平衡。

Node.js v7.7.2 Documentation

Throughout the documentation, you will see indications of a section’s stability. The Node.js API is still somewhat changing, and as it matures, certain parts are more reliable than others. Some are so proven, and so relied upon, that they are unlikely to ever change at all. Others are brand new and experimental, or known to be hazardous and in the process of being redesigned.

用法和示例:

node [options] [v8 options] [script.js | -e "script"] [arguments]

Assertion Testing断言测试

Node内置模块,用于断言。若表达式不符预期则抛出错误。种类很多但常用的只有几种。

  • assert(value[, message])
var assert = require('assert');
assert(true);// OK
assert(1);// OK
assert(false);// throws "AssertionError: false == true"
assert(false==0);// OK
  • assert.deepEqual(actual, expected[, message])
const assert = require('assert');

const o1 = {
  a: {
    b: 1
  }
};
const o2 = {
  a: {
    b: 2
  }
};
const o3 = {
  a: {
    b: 1
  }
};
const o4 = Object.create(o1);

assert.deepEqual(o1, o1); //OK
assert.deepEqual(o1, o2); // AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }
// values of b are different
assert.deepEqual(o1, o3); //OK
assert.deepEqual(o1, o4); // AssertionError: { a: { b: 1 } } deepEqual {}
// Prototypes are ignored
assert.deepEqual(o1, o4.__proto__); //OK

  • assert.deepStrictEqual(actual, expected[, message])
assert.deepEqual({a:1}, {a:'1'});// OK, because 1 == '1'
assert.deepStrictEqual({a:1}, {a:'1'});// because 1 !== '1' using strict equality
  • assert.doesNotThrow(block[, error][, message])

  • assert.equal(actual, expected[, message])

//相当于==
assert.equal(1, 1);// OK, 1 == 1
assert.equal(1, '1');// OK, 1 == '1'
assert.equal(1, 2);// AssertionError: 1 == 2
assert.equal({a: {b: 1}}, {a: {b: 1}});//AssertionError: { a: { b: 1 } } == { a: { b: 1 } }
{a:{b:1}}=={a:{b:1}};//false

  • assert.fail(actual, expected, message, operator)
  • assert.ifError(value)
  • assert.notDeepEqual(actual, expected[, message])
  • assert.notDeepStrictEqual(actual, expected[, message])
  • assert.notEqual(actual, expected[, message])
  • assert.notStrictEqual(actual, expected[, message])
  • assert.ok(value[, message])
  • assert.strictEqual(actual, expected[, message])

Buffer

在ES6引入TypedArray之前,JS中只有字符串数据类型,没有二进制数据类型;JS比较擅长字符串处理但处理二进制数据(比如TCP数据)就不足。 在Node中,定义了一个Buffer类,用于专门存放二进制文件的缓冲区,及方法处理,可以全局访问。Node中Buffer类是随Node内核 一起发布的核心库,为Node提供了一种存储原始数据的方法,可以处理二进制数据,每当需要在Node 中处理I/O操作中移动的数据时,就有可能使用。原始数据存放在Buffer类的实例中,一个Buffer类似于 一个整数数组,但对于V8堆内存之外的一块原始内存。

  • 与TypedArray关系

TypedArray构造函数可以接受Buffer实例作为参数生成一个二进制数组.二进制数组的操作,与Buffer对象的操作基本上是兼容的,只有轻微的差异。比如,二进制数组的slice方法返回原内存的拷贝,而Buffer对象的slice方法创造原内存的一个视图(view)。

  • 示例
// Creates a zero-filled Buffer of length 10.
const buf1 = Buffer.alloc(10);

// Creates a Buffer of length 10, filled with 0x1.
const buf2 = Buffer.alloc(10, 1);

// Creates an uninitialized buffer of length 10.
// This is faster than calling Buffer.alloc() but the returned
// Buffer instance might contain old data that needs to be
// overwritten using either fill() or write().
const buf3 = Buffer.allocUnsafe(10);

// Creates a Buffer containing [0x1, 0x2, 0x3].
const buf4 = Buffer.from([1, 2, 3]);

// Creates a Buffer containing UTF-8 bytes [0x74, 0xc3, 0xa9, 0x73, 0x74].
const buf5 = Buffer.from('tést');

// Creates a Buffer containing Latin-1 bytes [0x74, 0xe9, 0x73, 0x74].
const buf6 = Buffer.from('tést', 'latin-1');

  • 类的方法

    • Buffer.isEncoding():返回一个布尔值,表征是否为指定编码
    
      + Buffer.isBuffer():接受一个对象为参数,表征是否为Buffer实例
    
      ```Buffer.isBuffer(Date) // false ```
      + Buffer.byteLength():返回字符串实际占据的字节长度
      ```Buffer.byteLength('Hello', 'utf8') // 5  ```
      + Buffer.concat()
    
    

    var i1 = new Buffer(‘Hello’); var i2 = new Buffer(‘ ‘); var i3 = new Buffer(‘World’); Buffer.concat([i1, i2, i3], 10).toString() // ‘Hello Worl’ ```

  • 实例方法

    • write()
        var buf = new Buffer(5);
        buf.write('He');
        buf.write('l', 2);
        buf.write('lo', 3);
        console.log(buf.toString());
        // "Hello"
      
    • slice()
    • toString()
    • toJSON()

C/C++ Addons 插件

Node.js 插件是用 C 或 C++ 编写的动态链接共享对象,可以使用 require() 函数加载到 Node.js 中,且像普通的 Node.js 模块一样被使用。 它们主要用于为运行于 Node.js 的 JavaScript 和 C/C++ 库之间提供接口。

  • Hello world
    • Building
    • Linking to Node.js’ own dependencies
    • Loading Addons using require()
  • Native Abstractions for Node.js
  • Addon examples
    • Function arguments
    • Callbacks
    • Object factory
    • Function factory
    • Wrapping C++ objects
    • Factory of wrapped objects
    • Passing wrapped objects around
    • AtExit hooks
      • void AtExit(callback, args)

Child Process

默认情况下,在 Node.js 的父进程和衍生的子进程之间会建立 stdin、stdout 和 stderr 的管道。 这使得数据可以以非阻塞的方式在这些管道流通。 注意,有些程序会在内部使用行缓冲 I/O。 虽然这并不影响 Node.js,但这意味着发送到子过程的数据可能无法被立即消费。

Cluster(集群)

Command Line Options

  • Synopsis

  • Options
    • -v, –version
    • -h, –help
    • -e, –eval “script”
    • -p, –print “script”
    • -c, –check
    • -i, –interactive
    • -r, –require module
    • –no-deprecation
    • –trace-deprecation
    • –throw-deprecation
    • –no-warnings
    • –trace-warnings
    • –trace-sync-io
    • –trace-events-enabled
    • –trace-event-categories
    • –zero-fill-buffers
    • –preserve-symlinks
    • –track-heap-objects
    • –prof-process
    • –v8-options
    • –tls-cipher-list=list
    • –enable-fips
    • –force-fips
    • –openssl-config=file
    • –use-openssl-ca, –use-bundled-ca
    • –icu-data-dir=file
  • Environment Variables

Console

console 模块提供了一个简单的调试控制台,它与 Web 浏览器提供的 JavaScript 控制台的机制类似。

  • Class: Console
    • new Console(stdout[, stderr])
    • console.assert(value[, message][, …args])
    • console.dir(obj[, options])
    • console.error([data][, …args])
    • console.info([data][, …args])
    • console.log([data][, …args])
    • console.time(label)
    • console.timeEnd(label)
    • console.trace([message][, …args])
    • console.warn([data][, …args])

Crypto(加密)

  • Determining if crypto support is unavailable
  • Class: Certificate
    • new crypto.Certificate()
    • certificate.exportChallenge(spkac)
    • certificate.exportPublicKey(spkac)
    • certificate.verifySpkac(spkac)
  • Class: Cipher
    • cipher.final([output_encoding])
    • cipher.setAAD(buffer)
    • cipher.getAuthTag()
    • cipher.setAutoPadding(auto_padding=true)
    • cipher.update(data[, input_encoding][, output_encoding])
  • Class: Decipher
    • decipher.final([output_encoding])
    • decipher.setAAD(buffer)
    • decipher.setAuthTag(buffer)
    • decipher.setAutoPadding(auto_padding=true)
    • decipher.update(data[, input_encoding][, output_encoding])
  • Class: DiffieHellman
    • diffieHellman.computeSecret(other_public_key[, input_encoding][, output_encoding])
    • diffieHellman.generateKeys([encoding])
    • diffieHellman.getGenerator([encoding])
    • diffieHellman.getPrime([encoding])
    • diffieHellman.getPrivateKey([encoding])
    • diffieHellman.getPublicKey([encoding])
    • diffieHellman.setPrivateKey(private_key[, encoding])
    • diffieHellman.setPublicKey(public_key[, encoding])
    • diffieHellman.verifyError
  • Class: ECDH
    • ecdh.computeSecret(other_public_key[, input_encoding][, output_encoding])
    • ecdh.generateKeys([encoding[, format]])
    • ecdh.getPrivateKey([encoding])
    • ecdh.getPublicKey([encoding[, format]])
    • ecdh.setPrivateKey(private_key[, encoding])
    • ecdh.setPublicKey(public_key[, encoding])
  • Class: Hash
    • hash.digest([encoding])
    • hash.update(data[, input_encoding])
  • Class: Hmac
    • hmac.digest([encoding])
    • hmac.update(data[, input_encoding])
  • Class: Sign
    • sign.sign(private_key[, output_format])
    • sign.update(data[, input_encoding])
  • Class: Verify
    • verifier.update(data[, input_encoding])
    • verifier.verify(object, signature[, signature_format]) crypto module methods and properties
    • crypto.constants
    • crypto.DEFAULT_ENCODING
    • crypto.fips
    • crypto.createCipher(algorithm, password)
    • crypto.createCipheriv(algorithm, key, iv)
    • crypto.createCredentials(details)
    • crypto.createDecipher(algorithm, password)
    • crypto.createDecipheriv(algorithm, key, iv)
    • crypto.createDiffieHellman(prime[, prime_encoding][, generator][, generator_encoding])
    • crypto.createDiffieHellman(prime_length[, generator])
    • crypto.createECDH(curve_name)
    • crypto.createHash(algorithm)
    • crypto.createHmac(algorithm, key)
    • crypto.createSign(algorithm)
    • crypto.createVerify(algorithm)
    • crypto.getCiphers()
    • crypto.getCurves()
    • crypto.getDiffieHellman(group_name)
    • crypto.getHashes()
    • crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)
    • crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)
    • crypto.privateDecrypt(private_key, buffer)
    • crypto.privateEncrypt(private_key, buffer)
    • crypto.publicDecrypt(public_key, buffer)
    • crypto.publicEncrypt(public_key, buffer)
    • crypto.randomBytes(size[, callback])
    • crypto.setEngine(engine[, flags])
    • crypto.timingSafeEqual(a, b)
  • Notes
    • Legacy Streams API (pre Node.js v0.10)
    • Recent ECDH Changes
    • Support for weak or compromised algorithms
  • Crypto Constants
    • OpenSSL Options
    • OpenSSL Engine Constants
    • Other OpenSSL Constants
    • Node.js Crypto Constants

Debugger

Node.js 包含一个进程外的调试工具,可以通过基于 TCP 的协议和内置调试客户端访问。

``` $ node debug main.js < Debugger listening on 127.0.0.1:5858 connecting to 127.0.0.1:5858 … ok break in D:\me\webpack\webpack-demo\main.js:1 > 1 var x = 5; 2 setTimeout(() => { 3 debugger; debug> cont < hello break in D:\me\webpack\webpack-demo\main.js:3 1 var x = 5; 2 setTimeout(() => { > 3 debugger; 4 console.log(‘world’); 5 }, 1000); debug> next break in D:\me\webpack\webpack-demo\main.js:4 2 setTimeout(() => { 3 debugger; > 4 console.log(‘world’); 5 }, 1000); 6 console.log(‘hello’); debug> quit


- Watchers
- Command reference
  - Stepping
  - Breakpoints
  - Information
  - Execution control
  - Various
- Advanced Usage
- V8 Inspector Integration for Node.js

### DNS

- dns.getServers()
- dns.lookup(hostname[, options], callback)
  Supported getaddrinfo flags
- dns.lookupService(address, port, callback)
- dns.resolve(hostname[, rrtype], callback)
- dns.resolve4(hostname[, options], callback)
- dns.resolve6(hostname[, options], callback)
- dns.resolveCname(hostname, callback)
- dns.resolveNaptr(hostname, callback)
- dns.resolveNs(hostname, callback)
- dns.resolvePtr(hostname, callback)
- dns.resolveSoa(hostname, callback)
- dns.resolveSrv(hostname, callback)
- dns.resolveTxt(hostname, callback)
- dns.reverse(ip, callback)
- dns.setServers(servers)
- Error codes
- Implementation considerations
  + dns.lookup()
  + dns.resolve(), dns.resolve*() and dns.reverse()

### Domain(deprecated)

### Errors

- Error Propagation and Interception
  - Node.js style callbacks
- Class: Error
  - new Error(message)
  - Error.captureStackTrace(targetObject[,constructorOpt])
  - Error.stackTraceLimit
  - error.message
  - error.stack
- Class: RangeError
- Class: ReferenceError
- Class: SyntaxError
- Class: TypeError
- Exceptions vs. Errors
- System Errors
  - Class: System Error
    - error.code
    - error.errno
    - error.syscall
    - error.path
    - error.address
    - error.port
  - Common System Errors

> Node是单线程运行环境,一旦抛出异常未被捕获便引起整个进程崩溃,一般有三种方法传播一个错误。

- throw抛出异常

> 最常用,但无法捕获异步运行代码抛出的异常。
  
    ```
    try {
      process.nextTick(() => {
        throw new Error('error')
      });
    } catch (err) {
      //can not catch it
      concole.log(err);
    }   
    try {
      setTimeout(() => {
        throw new Error('error')
      }, 10)
    } catch (err) {
      //can not catch it
      console.log(err);
    }
//   使用process.nextTick和setTimeout在下一轮事件循环抛出两个异常代表一步操作错误,均无法被catch捕获,因catch已运行结束 
//解决方案之一:将错误代码也放到异步执行
    function async(cb, err) {
      setTimeout(function() {
        try {
          if (true)
            throw new Error("woops!");
          else
            cb("done");
        } catch(e) {
          err(e);
        }
      }, 2000)
    }
    
    async(function(res) {
      console.log("received:", res);
    }, function(err) {
      console.log("Error: async threw an exception:", err);
    });
    // Error: async threw an exception: Error: woops!Node很少用此方法,如JSON.parse时
    ```

- 将error对象传递给回调函数,发出错误

> Node将错误对象作为首个参数传入回调函数

fs.readFile(‘/foo.txt’, function(err, data) { if (err !== null) throw err; console.log(data); });


- 通过EventEmitter接口,发出error事件

var EventEmitter = require(‘events’).EventEmitter; var emitter = new EventEmitter(); emitter.emit(‘error’, new Error(‘something bad happened’)); //如果没有对error事件部署监听函数,会导致整个应用程序崩溃。所以,一般总是必须同时部署下面的代码。 emitter.on(‘error’, function(err) { console.error(‘出错:’ + err.message); });


- uncaughtException事件

> 异常未被捕获便触发

var logger = require(‘tracer’).console(); process.on(‘uncaughtException’, function(err) { console.error(‘Error caught in uncaughtException event:’, err); //uncaughtException触发后,最好记录错误日志,然后结束Node进程 logger.log(err); process.exit(1); }); try { setTimeout(function(){ throw new Error(“error”); },1); } catch (err) { //can not catch it console.log(err); }


- unhandledRejection事件

### Events模块

> 回调函数让Node可以处理异步操作,但其只能有开始和结束两种状态。对于多状态的异步操作,Node
提供EventEmitter接口,通过事件解决多状态异步操作响应问题。

- 概述

> EventEmitter是event模块提供的一个接口,可以在任何对象上部署。

- Passing arguments and this to listeners
- Asynchronous vs. Synchronous
- Handling events only once
- Error events
- Class: EventEmitter
  - Event: 'newListener'
  - Event: 'removeListener'
  - EventEmitter.defaultMaxListeners
  - emitter.addListener(eventName, listener)
  - emitter.emit(eventName[, ...args])
  - emitter.eventNames()
  - emitter.getMaxListeners()
  - emitter.listenerCount(eventName)
  - emitter.listeners(eventName)
  - emitter.on(eventName, listener)
  - emitter.once(eventName, listener)
  - emitter.prependListener(eventName, listener)
  - emitter.prependOnceListener(eventName, listener)
  - emitter.removeAllListeners([eventName])
  - emitter.removeListener(eventName, listener)
  - emitter.setMaxListeners(n)

var EventEmitter = require(‘events’).EventEmitter; var emitter = new EventEmitter(); //事件发生器的实例方法用on监听事件,然后emit用来发出事件。 var EventEmitter = require(‘events’).EventEmitter; var emitter = new EventEmitter();

emitter.on(‘event1’, () => console.log(‘event1 has occred’)); emitter.on(‘event2’, () => console.log(‘event2 has occred’)); //EventEmitter对象的事件触发和监听是同步的 console.log(‘start’); emitter.emit(‘event1’); emitter.emit(‘event2’); console.log(‘end’);


- EventEmitter接口的部署

> Event Emitter 接口可以部署在任意对象上,使得这些对象也能订阅和发布消息。

var EventEmitter = require(‘events’).EventEmitter; var util = require(‘util’);

function Dog(name) { this.name = name; }

// Dog.prototype.proto = EventEmitter.prototype; //Dog.prototype=Object.create(EventEmitter.prototype); util.inherits(Dog, EventEmitter);//利用内置继承

var haha = new Dog(‘haha’); haha.on(‘bark’, function() { console.log(this.name + ‘ barked…’); });

haha.emit(‘bark’); //hahabarked…


- Event Emitter实例方法
    + emitter.on(name, f) 对事件name指定监听函数f
    + emitter.addListener(name, f) addListener是on方法的别名
    + emitter.once(name, f) 与on方法类似,但是监听函数f是一次性的,使用后自动移除
    + emitter.listeners(name) 返回一个数组,成员是事件name所有监听函数
    + emitter.removeListener(name, f) 移除事件name的监听函数f(具名函数)
    + emitter.setMaxListeners(num) Node默认允许同一个事件最多可以指定10个回调函数。移除num个事件
    + emitter.removeAllListeners(name) 移除事件name的所有监听函数
    + emitter.listeners(f) 返回该事件所有回调函数组成的数组
- 错误捕获:事件处理过程中抛出的错误可用try-catch捕获
- 事件类型: Events模块默认支持两个事件
    + newListener事件:添加新的回调函数时触发。
    + removeListener事件:移除回调时触发。

### File System

> Node提供一组类似UNIX(POSIX)标准的文件操作API

- Buffer API
- Class: fs.FSWatcher
  - Event: 'change'
  - Event: 'error'
  - watcher.close()
- Class: fs.ReadStream
  - Event: 'close'
  - Event: 'open'
  - readStream.bytesRead
  - readStream.path
- Class: fs.Stats
  - Stat Time Values
- Class: fs.WriteStream
  - Event: 'close'
  - Event: 'open'
  - writeStream.bytesWritten
  - writeStream.path
- fs.access(path[, mode], callback)
- fs.accessSync(path[, mode])
- fs.appendFile(file, data[, options], - callback)
- fs.appendFileSync(file, data[, options])
- fs.chmod(path, mode, callback)
- fs.chmodSync(path, mode)
- fs.chown(path, uid, gid, callback)
- fs.chownSync(path, uid, gid)
- fs.close(fd, callback)
- fs.closeSync(fd)
- fs.constants
- fs.createReadStream(path[, options])
- fs.createWriteStream(path[, options])
- fs.existsSync(path)
- fs.fchmod(fd, mode, callback)
- fs.fchmodSync(fd, mode)
- fs.fchown(fd, uid, gid, callback)
- fs.fchownSync(fd, uid, gid)
- fs.fdatasync(fd, callback)
- fs.fdatasyncSync(fd)
- fs.fstat(fd, callback)
- fs.fstatSync(fd)
- fs.fsync(fd, callback)
- fs.fsyncSync(fd)
- fs.ftruncate(fd, len, callback)
- fs.ftruncateSync(fd, len)
- fs.futimes(fd, atime, mtime, callback)
- fs.futimesSync(fd, atime, mtime)
- fs.lchmod(path, mode, callback)
- fs.lchmodSync(path, mode)
- fs.lchown(path, uid, gid, callback)
- fs.lchownSync(path, uid, gid)
- fs.link(existingPath, newPath, callback)
- fs.linkSync(existingPath, newPath)
- fs.lstat(path, callback)
- fs.lstatSync(path)
- fs.mkdir(path[, mode], callback)
- fs.mkdirSync(path[, mode])
- fs.mkdtemp(prefix[, options], callback)
- fs.mkdtempSync(prefix[, options])
- fs.open(path, flags[, mode], callback)
- fs.openSync(path, flags[, mode])
- fs.read(fd, buffer, offset, length, - position, callback)
- fs.readdir(path[, options], callback)
- fs.readdirSync(path[, options])
- fs.readFile(file[, options], callback)
- fs.readFileSync(file[, options])
- fs.readlink(path[, options], callback)
- fs.readlinkSync(path[, options])
- fs.readSync(fd, buffer, offset, length, - position)
- fs.realpath(path[, options], callback)
- fs.realpathSync(path[, options])
- fs.rename(oldPath, newPath, callback)
- fs.renameSync(oldPath, newPath)
- fs.rmdir(path, callback)
- fs.rmdirSync(path)
- fs.stat(path, callback)
- fs.statSync(path)
- fs.symlink(target, path[, type], callback)
- fs.symlinkSync(target, path[, type])
- fs.truncate(path, len, callback)
- fs.truncateSync(path, len)
- fs.unlink(path, callback)
- fs.unlinkSync(path)
- fs.unwatchFile(filename[, listener])
- fs.utimes(path, atime, mtime, callback)
- fs.utimesSync(path, atime, mtime)
- fs.watch(filename[, options][, listener])
  - Caveats
    - Availability
    - Inodes
    - Filename Argument
- fs.watchFile(filename[, options], listener)
- fs.write(fd, buffer[, offset[, length[, - position]]], callback)
- fs.write(fd, string[, position[, -encoding]], callback)
- fs.writeFile(file, data[, options],  callback)
- fs.writeFileSync(file, data[, options])
- fs.writeSync(fd, buffer[, offset[,  length[, position]]])
- fs.writeSync(fd, string[, position[, encoding]])
- FS Constants
  - File Access Constants
  - File Open Constants
  - File Type Constants
  - File Mode Constants- 
- readFile()/readFileSync()
    + readFile():异步读取数据
    ```
    fs.readFile('./image.png', function (err, buffer) {
      if (err) throw err;
      process(buffer);//若是相对路径则是相对当前脚本所在的路径
    });
    ```
    + readFileSync():同步读取文件,返回一个字符串。
    ```
    var text = fs.readFileSync(fileName, 'utf8');   
    // 将文件按行拆成数组
    text.split(/\r?\n/).forEach(function (line) {
      // ...
    });
    ```

- writeFile()/writeFileSync()

    + writeFile():异步写入
    ```
    fs.writeFile('message.txt', 'Hello Node.js','utf8', (err) => {
      if (err) throw err;
      console.log('It\'s saved!');
    });
    ```
    + writeFileSync()
- exists(path,callback):判断给定路径是否存在
- mkdir()/writeFile()/readFile()
- mkdirSync()/writeFileSync()/readFileSync()
- readdir()/readdirSync() :readdir方法用于读取目录,返回一个所包含的文件和子目录的数组。
- start():参数为一文件或目录,产生一个包含该文件或目录具体信息的对象。判断处理的是文件还是目录。
- watchFile()/unwatchFile():监听文件变化
- createReadStream():打开大文件,创建一个读取操作的数据流。
- createWriteStream():创建一个写入数据流对象,其write方法用于写入数据,end方法用于结束写入操作。
  
    
    
### Globals

> Global Object:所有属性均可在程序的任何地方访问,即全局变量。相当于浏览器中的window。
所有对象都是global对象的属性。

- 全局对象
    + global
    类似window对象,但每个文件都是模块,其内变量均为该模块私有其它模块无法获取
    + process
    表示Node所处的当前进程,允许开发者与之互动
    + console
    提供命令行环境中的标准输入输出功能
- 全局函数
    + setTimeout()
    + clearTimeout()
    + setInterval()
    + clearInterval()
    + require():加载模块
    + Buffer():操作二进制数据
- 全局变量:在最外层定义的变量,全局对象的属性,隐式定义的变量
    + __filename:当前运行脚本文件名
    + __dirname:当前运行脚本所在目录
    + 伪全局变量:实际为模块内部的局部变量,指向对象个面具模块不同而不同,但所以模块均适用。
        * module
        * module.exports
        * exports
Node中不可能在最外层定义变量,因所有用户代码都属于当前模块,而模块本身不是最外层上下文。

- __filename: 当前正在执行的脚本文件名。将输出文件所在位置的绝对路径且和命令行参数所指定的
文件名不一定相同。在模块中返回模块文件路径。

//main.js
console.log(__filename);// 输出全局变量 __filename 的值 $ node main.js D:\me\webpack\webpack-demo\main.js


- __dirname:当前执行脚本所在的目录

//main.js
console.log(__dirname);// 输出全局变量 __dirname 的值 $ node main.js D:\me\webpack\webpack-demo


### HTTP

- JS函数调用堆栈:函数被调用时便被压入堆栈顶部,运行完成则被移出堆栈顶部;其数据结构为FIFO。
- 回调:
    异步编程最基本的方法,node按顺序执行异步逻辑时一般采用后续传递的方式。
    即将后续逻辑封装在回调函数中作为起始函数的参数,逐层嵌套,以此让程序按期望执行。
    ```
    //callback.js
    fuction learn(sth){
        console.log(sth);
    }
    function we(callback,sth){
        sth+='is cool';
        callback(sth);
    }
    we(learn,'Node');
    we((sth)=>console.log(sth),'react');

    ```

- 同步/异步:关注的是消息通信机制 (synchronous communication/ asynchronous communication)。
    同步:由调用者主动等待这个调用的结果。执行任务执行顺序与任务排列顺序一致,上一步任务执行完毕才能开始下一步程序。
    异步:调用在发出之后,这个调用就直接返回了,所以没有返回结果。每个任务都有一个或多个回调函数,
    程序执行顺序与任务排列顺序无关。
- I/O:磁盘的写入和读出,数据的输入和输出
- 单线程/多线程:前者--程序功能按顺序执行,前续功能执行结束后续功能才能执行开始;后者:反之。
- 阻塞/非阻塞:关注的是程序在等待调用结果(消息,返回值)时的状态。同步的原因导致阻塞结果,异步的原因导致非阻塞结果。
    阻塞:调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
    非阻塞:在不能立刻得到结果之前,该调用不会阻塞当前线程。
- 事件/事件驱动:函数执行的一种方式,即为某个事件注册了回调函数,该函数不会立即执行而是等事件被触发(EventEmitter)之后才执行。
![event loop][http://www.runoob.com/wp-content/uploads/2015/09/event_loop.jpg]
    事件类似于主题,其上的事件处理函数相当于观察者(Observer)。
    ```
    var events = require('events');
    // 创建 eventEmitter 对象
    var eventEmitter = new events.EventEmitter();
    var connectHandler = function connected() {
       console.log('连接成功。');
       eventEmitter.emit('data_received');
    }
    eventEmitter.on('connection', connectHandler);
    eventEmitter.on('data_received', function(){
       console.log('数据接收成功。');
    });
    eventEmitter.emit('connection');
    console.log("程序执行完毕。");
    ```
- 基于事件驱动的回调:注册事件驱动的回调。
- 事件循环:event loop一种事件管理机制(FIFO),若有大量的异步操作,IO的耗时操作及计时器控制的延时操作,
    它们完成的时候都要调用相应的回调函数,
    从而完成一些密集的任务,又不会阻塞整个程序执行的流程。
    - Node是单线程单进程的应用程序,通过事件和回调支持并发故性能高。
    - Node的每个API都是作为一个独立线程运行的异步的,使用异步函数调用并处理并发。
    - Node基本上所有事件机制都是设计模式中的观察者模式。
    - 单线程类似进入一个while(true)循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者。若有事件发生则回调。
- HTTP小爬虫

var http = require(‘http’); var url = ‘http://www.imooc.com/video/7965’;

http.get(url, (res) => { var html = ‘’; res.on(‘data’, data => html += data) res.on(‘end’, () => console.log(html)) }).on(‘error’, () => console.log(‘error…’))


- 函数传递是如何让HTTP服务器工作的:事件驱动与回调

    ```
    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);
    ```

### HTTPS

- Class: https.Agent
- Class: https.Server
  - server.setTimeout(msecs, callback)
  - server.timeout
- https.createServer(options[, requestListener])
  - server.close([callback])
  - server.listen(handle[, callback])
  - server.listen(path[, callback])
  - server.listen(port[, host][, backlog][, callback])
- https.get(options, callback)
- https.globalAgent
- https.request(options, callback)

### Modules

> Modules是Node应用程序的基本组成部分,文件和模块一一对应,使Node文件可以相互调用

- Accessing the main module
- Addenda: Package Manager Tips
- All Together...
- Caching
  - Module Caching Caveats
- Core Modules
- Cycles
- File Modules
- Folders as Modules
- Loading from node_modules Folders
- Loading from the global folders
- The module wrapper
- The module Object
  - module.children
  - module.exports
  - exports shortcut
  - module.filename
  - module.id
  - module.loaded
  - module.parent
  - module.require(id) 
- Node提供了exports和require两个对象,前者是模块公开的接口,后者用于从外部获取一个模块的接口即所获取模块的exports对象。

//hello.js exports.world=function(){}//通过exports对象把world作为模块的访问接口 //main.js var world=require(‘./hello’);//加载该模块便可访问hello.js中exports对象的成员函数了。 module.exports=function(){}/只把一个对象封装到模块中, 外部引用该模块时其接口对象即要输出的Hello对象本身,而非原先的exports/


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

![http://www.runoob.com/wp-content/uploads/2014/03/nodejs-require.jpg][http://www.runoob.com/wp-content/uploads/2014/03/nodejs-require.jpg]
    Node中的四类模块(一种原生模块三种文件模块)
    1. 原生模块:http,fs,path等
    2. ./,../相对路径的文件模块
    3. /pathtomodule/mod,绝对路径模块
    4. mod,非原生模块的文件模块

### Net

- Class: net.Server
  - Event: 'close'
  - Event: 'connection'
  - Event: 'error'
  - Event: 'listening'
  - server.address()
  - server.close([callback])
  - server.getConnections(callback)
  - server.listen(handle[, backlog][, callback])
  - server.listen(options[, callback])
  - server.listen(path[, backlog][, callback])
  - server.listen([port][, hostname][, backlog][- , callback])
  - server.listening
  - server.maxConnections
  - server.ref()
  - server.unref()
- Class: net.Socket
  - new net.Socket([options])
  - Event: 'close'
  - Event: 'connect'
  - Event: 'data'
  - Event: 'drain'
  - Event: 'end'
  - Event: 'error'
  - Event: 'lookup'
  - Event: 'timeout'
  - socket.address()
  - socket.bufferSize
  - socket.bytesRead
  - socket.bytesWritten
  - socket.connect(options[, connectListener])
  - socket.connect(path[, connectListener])
  - socket.connect(port[, host][, - connectListener])
  - socket.connecting
  - socket.destroy([exception])
  - socket.destroyed
  - socket.end([data][, encoding])
  - socket.localAddress
  - socket.localPort
  - socket.pause()
  - socket.ref()
  - socket.remoteAddress
  - socket.remoteFamily
  - socket.remotePort
  - socket.resume()
  - socket.setEncoding([encoding])
  - socket.setKeepAlive([enable][, initialDelay])
  - socket.setNoDelay([noDelay])
  - socket.setTimeout(timeout[, callback])
  - socket.unref()
  - socket.write(data[, encoding][, callback])
- net.connect(options[, connectListener])
- net.connect(path[, connectListener])
- net.connect(port[, host][, connectListener])
- net.createConnection(options[, connectListener])
- net.createConnection(path[, connectListener])
- net.createConnection(port[, host][, connectListener])
- net.createServer([options][, connectionListener])
- net.isIP(input)
- net.isIPv4(input)
- net.isIPv6(input)

### OS

- os.EOL
- os.arch()
- os.constants
- os.cpus()
- os.endianness()
- os.freemem()
- os.homedir()
- os.hostname()
- os.loadavg()
- os.networkInterfaces()
- os.platform()
- os.release()
- os.tmpdir()
- os.totalmem()
- os.type()
- os.uptime()
- os.userInfo([options])
- OS Constants
  - Signal Constants
  - Error Constants
    - POSIX Error Constants
    - Windows Specific Error Constants
  - libuv Constants

### Path

>为路由提供请求的URL和其它需要的GET/POST参数,而后据此执行程序。

- Windows vs. POSIX
- path.basename(path[, ext])
- path.delimiter
- path.dirname(path)
- path.extname(path)
- path.format(pathObject)
- path.isAbsolute(path)
- path.join([...paths])
- path.normalize(path)
- path.parse(path)
- path.posix
- path.relative(from, to)
- path.resolve([...paths])
- path.sep
- path.win32

### Process

> Node是单线程事件驱动处理并发的,每个子进程都有三个流对象:child.stdin,child.stdout,
child.stderr.可能会共享父进程的stdio流或者可以是独立的被导流的流对象。

- Process Events
  - Event: 'beforeExit'
  - Event: 'disconnect'
  - Event: 'exit'
  - Event: 'message'
  - Event: 'rejectionHandled'
  - Event: 'uncaughtException'
  - Warning: Using 'uncaughtException' correctly
  - Event: 'unhandledRejection'
  - Event: 'warning'
  - Emitting custom warnings
  - Signal Events
- process.abort()
- process.arch
- process.argv
- process.argv0
- process.channel
- process.chdir(directory)
- process.config
- process.connected
- process.cpuUsage([previousValue])
- process.cwd()
- process.disconnect()
- process.emitWarning(warning[, name][, ctor])
  - Avoiding duplicate warnings
- process.env
- process.execArgv
- process.execPath
- process.exit([code])
- process.exitCode
- process.getegid()
- process.geteuid()
- process.getgid()
- process.getgroups()
- process.getuid()
- process.hrtime([time])
- process.initgroups(user, extra_group)
- process.kill(pid[, signal])
- process.mainModule
- process.memoryUsage()
- process.nextTick(callback[, ...args])
- process.pid
- process.platform
- process.release
- process.send(message[, sendHandle[, options]][, callback])
- process.setegid(id)
- process.seteuid(id)
- process.setgid(id)
- process.setgroups(groups)
- process.setuid(id)
- process.stderr
- process.stdin
- process.stdout
  - A note on process I/O
- process.title
- process.umask([mask])
- process.uptime()
- process.version
- process.versions
  - Exit Codes
- 创建子进程方法:
    + exec-child_process.exec
    + spawn-child_process.spawn
    + fork-child_process.fork

### Punycode

### Query Strings

- querystring.escape(str)
- querystring.parse(str[, sep[, eq[, options]]])
- querystring.stringify(obj[, sep[, eq[, options]]])
- querystring.unescape(str)

### Readline

- Class: Interface
  - Event: 'close'
  - Event: 'line'
  - Event: 'pause'
  - Event: 'resume'
  - Event: 'SIGCONT'
  - Event: 'SIGINT'
  - Event: 'SIGTSTP'
  - rl.close()
  - rl.pause()
  - rl.prompt([preserveCursor])
  - rl.question(query, callback)
  - rl.resume()
  - rl.setPrompt(prompt)
  - rl.write(data[, key])
  - readline.clearLine(stream, dir)
  - readline.clearScreenDown(stream)
  - readline.createInterface(options)
    - Use of the completer Function
  - readline.cursorTo(stream, x, y)
  - readline.emitKeypressEvents(stream[, interface])
  - readline.moveCursor(stream, dx, dy)
- Example: Tiny CLI
- Example: Read File Stream Line-by-Line

### REPL

- Design and Features
  - Commands and Special Keys
  - Default Evaluation
    - JavaScript Expressions
    - Global and Local Scope
    - Accessing Core Node.js Modules
    - Assignment of the _ (underscore) variable
  - Custom Evaluation Functions
    - Recoverable Errors
  - Customizing REPL Output
- Class: REPLServer
  - Event: 'exit'
  - Event: 'reset'
  - replServer.defineCommand(keyword, cmd)
  - replServer.displayPrompt([preserveCursor])
  - repl.start([options])
- The Node.js REPL
  - Environment Variable Options
  - Using the Node.js REPL with advanced line-editors
  - Starting multiple REPL instances against a single running instance

### Stream

> Stream是一个抽象接口,Node中很多对象(request,stout)已实现。

Stream 四种流类型:
- Readable
- Writable
- Duplex 可读可写操作.
- Transform
所有Stream对象都是EventEmitter的实例,常见:
- data
- end 没有更多的数据可读时触发。
- error
- finish 所有数据已被写入到底层系统时触发。

var fs = require(‘fs’); var readStream = fs.createReadStream(‘package.json’); readStream .on(‘data’, chunk => { console.log(‘data emits’); console.log(Buffer.isBuffer(chunk)); // console.log(chunk.toString(‘utf-8’)); readStream.pause(); setTimeout(() => { console.log(‘data pause end’); readStream.resume() }, 10) }) .on(‘readable’, () => console.log(‘data readable’)) .on(‘end’, () => console.log(‘data ends’)) .on(‘close’, () => console.log(‘data close’)) .on(‘error’, e => console.log(‘data read error’ + e)) //pipe读写 var readable = require(‘stream’).Readable; var writable = require(‘stream’).Writable;

var readStream = new readable();
var writStream = new writable();
readStream.push('I');
readStream.push('Love');
readStream.push('Node\n');
readStream.push(null);

writStream._write = (chunk, encode, cb) => {
  console.log(chunk.toString());
  cb()
}
readStream.pipe(writStream); ```

String Decoder

  • Class: new StringDecoder([encoding])
    • stringDecoder.end([buffer])
    • stringDecoder.write(buffer)

Timers

  • Class: Immediate
  • Class: Timeout
    • timeout.ref()
    • timeout.unref()
  • Scheduling Timers
    • setImmediate(callback[, …args])
    • setInterval(callback, delay[, …args])
    • setTimeout(callback, delay[, …args])
  • Cancelling Timers
    • clearImmediate(immediate)
    • clearInterval(timeout)
    • clearTimeout(timeout)

TTY

  • Class: tty.ReadStream
    • readStream.isRaw
    • readStream.setRawMode(mode)
  • Class: tty.WriteStream
  • Event: ‘resize’
    • writeStream.columns
    • writeStream.rows
  • tty.isatty(fd)

Tracing

UDP/Datagram

URL

  • URL Strings and URL Objects
    • urlObject.auth
    • urlObject.hash
    • urlObject.host
    • urlObject.hostname
    • urlObject.href
    • urlObject.path
    • urlObject.pathname
    • urlObject.port
    • urlObject.protocol
    • urlObject.query
    • urlObject.search
    • urlObject.slashes
  • url.format(urlObject)
  • url.format(URL[, options])
  • url.parse(urlString[, parseQueryString[, - slashesDenoteHost]])
  • url.resolve(from, to)
  • Escaped Characters
  • The WHATWG URL API
    • Class: URL
      • Constructor: new URL(input[, base])
      • url.hash
      • url.host
      • url.hostname
      • url.href
      • url.origin
      • url.password
      • url.pathname
      • url.port
      • url.protocol
      • url.search
      • url.searchParams
      • url.username
      • url.toString()
      • url.toJSON()
    • Class: URLSearchParams
    • Constructor: new URLSearchParams([init])
    • urlSearchParams.append(name, value)
    • urlSearchParams.delete(name)
    • urlSearchParams.entries()
    • urlSearchParams.forEach(fn[, thisArg])
    • urlSearchParams.get(name)
    • urlSearchParams.getAll(name)
    • urlSearchParams.has(name)
    • urlSearchParams.keys()
    • urlSearchParams.set(name, value)
    • urlSearchParams.sort()
    • urlSearchParams.toString()
    • urlSearchParams.values()
    • urlSearchParams@@iterator
  • require(‘url’).domainToASCII(domain)
  • require(‘url’).domainToUnicode(domain)
  • Percent-Encoding in the WHATWG URL Standard

Utilities

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

  • util.inherits(constructor, superConstructor):实现对象间原型继承的函数

JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。 JavaScript 没有 提供对象继承的语言级别特性,而是通过原型复制来实现的。 ``` var util = require(‘util’);

function Base() { this.name = ‘base’; this.base = 1990; this.sayHello = function() { console.log(‘Hello’ + this.name); } } Base.prototype.showName = function() { console.log(this.name); }

function Sub() { this.name = ‘sub’; }

util.inherits(Sub, Base); var objBase = new Base(); objBase.showName(); objBase.sayHello(); console.log(objBase); var objSub = new Sub(); objSub.showName(); //objSub.sayHello();//TypeError: objSub.sayHello is not a function,Sub仅继承原型中定义的函数 console.log(objSub);


- util.inspect: 将任意对象转换为字符串,常用语调试及错误输出,至少接受一个object参数。

//util.inspect 并不会简单地直接把对象转换为字符串,即使该对 象定义了toString 方法也不会调用。 var util = require(‘util’); function Person() { this.name = ‘haha’; this.toString = function() { return this.name; } } var o = new Person(); console.log(util.inspect(o)); console.log(util.inspect(o, true)); console.log(util.inspect(o, true, 3)); console.log(util.inspect(o, true, 3, [(1, 0, 0)])); //输出如下 Person { name: ‘haha’, toString: [Function] } Person { name: ‘haha’, toString: { [Function] [length]: 0, [name]: ‘’, [arguments]: null, [caller]: null, [prototype]: { [constructor]: [Circular] } } } Person { name: ‘haha’, toString: { [Function] [length]: 0, [name]: ‘’, [arguments]: null, [caller]: null, [prototype]: { [constructor]: [Circular] } } } Person { name: ‘haha’, toString: { [Function] [length]: 0, [name]: ‘’, [arguments]: null, [caller]: null, [prototype]: { [constructor]: [Circular] } } } ```

  • util.isArray(object)
  • util.isRegExp(object)
  • util.isDate(object)
  • util.isError(object)

V8

  • v8.getHeapSpaceStatistics()
  • v8.getHeapStatistics()
  • v8.setFlagsFromString(string)

VM

ZLIB

Tags: ,

Categories:

Updated:

Leave a Comment

comments powered by Disqus