Node.js基礎 23456:全局對象,回調函數,模塊,事件,讀寫文件(同步,異步)

全局對象

相似的,在瀏覽器中有window
全局變量在全部模塊中均可使用。不須要引用等。
全局變量
console,setTimeout,require()html

全局變量在全部模塊中均可使用。 如下變量雖然看起來像全局變量,但實際上不是(global裏面沒有如下屬性)。 它們的做用域只在模塊內,詳見 文檔:node

__dirname
__filename
exports
module
require()

回調函數

與js同樣,如:react

function callFunction(fun, name) {
    fun(name);
}

callFunction(function(name) {
    console.log(name + ' Bye');
}, 'mtt');

模塊

一個大項目必定是分紅一個個模塊的,通常來講,一個文件就是一個模塊。
模塊使用方法:
在這裏插入圖片描述
向外暴露的是一個對象。
在這裏插入圖片描述
咱們require()的時候,接收的也是一個對象.
因此也能夠這樣寫:
在這裏插入圖片描述
在這裏插入圖片描述
app.jsapi

var stuff = require('./count');



console.log(stuff.counter(['ruby', 'nodejs', 'react']));
console.log(stuff.adder(3));//6.14

能夠使用別的模塊裏的變量(閉包)
count.js瀏覽器

var adder = function(a) {
    return `the sum of the 2 numbers is ${a+pi}`;
}

var pi = 3.14;

module.exports = {
    counter: function(arr) {
        return "There are " + arr.length + " elements in the array";
    },
    adder: adder
}

事件

http://nodejs.cn/api/events.htmlruby

大多數 Node.js 核心 API 構建於慣用的異步事件驅動架構,其中某些類型的對象(又稱觸發器,Emitter)會觸發命名事件來調用函數(又稱監聽器,Listener)。

例如,net.Server 會在每次有新鏈接時觸發事件,fs.ReadStream會在打開文件時觸發事件,stream會在數據可讀時觸發事件。閉包

全部能觸發事件的對象都是 EventEmitter 類的實例。 這些對象有一個 eventEmitter.on() 函數,用於將一個或多個函數綁定到命名事件上。 事件的命名一般是駝峯式的字符串。架構

EventEmitter 對象觸發一個事件時,全部綁定在該事件上的函數都會被同步地調用。app

例子,一個簡單的 EventEmitter 實例,綁定了一個監聽器。 eventEmitter.on() 用於註冊監聽器,eventEmitter.emit() 用於觸發事件。異步

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('觸發事件');
});
myEmitter.emit('event');

總結理解:

  1. 觸發器(Emitter)會觸發監聽器(Listener),而後函數會被同步調用。
  2. myEmitter.on('event', () => {});用來 綁定事件與函數(註冊監聽器,eventEmitter.emit() 用於觸發事件
  3. 例子:net.Server 會在每次有新鏈接時觸發事件,fs.ReadStream會在打開文件時觸發事件,stream會在數據可讀時觸發事件。

傳參數與 this 到監聽器

http://nodejs.cn/api/events.h...

eventEmitter.emit() 方法能夠傳任意數量的參數到監聽器函數。 當監聽器函數被調用時,this 關鍵詞會被指向監聽器所綁定的EventEmitter 實例。
const EventEmitter = require('events');
class MyEmitter extends EventEmitter{}
const myEmitter1 = new MyEmitter();
myEmitter1.on('exxx',function (a, b) {
    console.log(a, b, this, this===myEmitter1);
})


myEmitter1.emit('exxx','我是a','我是b')

在這裏插入圖片描述
總結:

  1. eventEmitter.emit() 從第二個參數開始,會把參數傳到監聽器綁定的那個函數裏面,做爲第一個開始.
  2. this表明調用on的那個實例

事件只處理一次

當使用 eventEmitter.on() 註冊監聽器時,監聽器會在每次觸發命名事件時被調用。

const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// 打印: 1
myEmitter.emit('event');
// 打印: 2

使用 eventEmitter.once() 能夠註冊最多可調用一次的監聽器。 當事件被觸發時,監聽器會被註銷,而後再調用。

const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// 打印: 1
myEmitter.emit('event');
// 不觸發

evnets是核心庫,直接require('events')
手動用代碼觸發事件。
util(實用工具)(nodejs核心工具庫)
http://nodejs.cn/api/util.htm...

var events = require('events');
var util = require('util');//nodejs工具庫

var Person = function(name) {
    this.name = name
}

util.inherits(Person, events.EventEmitter);
//讓Person繼承events.EventEmitter(也能夠用ES6寫法的extends關鍵字),讓他擁有能夠綁定事件,觸發事件的功能。
var xiaoming = new Person('xiaoming');
var lili = new Person('lili');
var lucy = new Person('lucy');
//新生成三個對象
var person = [xiaoming, lili, lucy];

person.forEach(function(person) {
    person.on('speak', function(message) {
        console.log(person.name + " said: " + message);//給每個新對象綁定事件
    })
})

xiaoming.emit('speak', 'hi');//每個新對象均可以觸發事件
lucy.emit('speak', 'I want a curry');

讀寫文件(同步,異步)

文件系統:http://nodejs.cn/api/fs.html
fs 模塊用於以一種相似標準 POSIX 函數的方式與文件系統進行交互。

使用方法以下:

const fs = require('fs');
全部的文件系統操做都有同步異步兩種形式。

異步

異步形式的最後一個參數是完成時的回調函數。 傳給回調函數的參數取決於具體方法,但第一個參數會保留給異常。 若是操做成功完成,則第一個參數(異常)會是 nullundefined

const fs = require('fs');

fs.unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('成功刪除 /tmp/hello');
});

同步

當使用同步操做時,任何異常都會當即拋出,可使用 try/catch 處理異常。

const fs = require('fs');

try {
  fs.unlinkSync('/tmp/hello');
  console.log('成功刪除 /tmp/hello');
} catch (err) {
  // 處理異常。
}

同步異步注意

異步的方法不能保證執行順序。 因此下面的例子可能會出錯,由於 fs.stat() 可能在 fs.rename() 以前完成:

fs.rename('/tmp/hello', '/tmp/world', (err) => {
  if (err) throw err;
  console.log('重命名完成');
});
fs.stat('/tmp/world', (err, stats) => {
  if (err) throw err;
  console.log(`文件屬性: ${JSON.stringify(stats)}`);
});
要想按順序執行操做,須要把 fs.stat() 放到 fs.rename() 的回調函數中:

fs.rename('/tmp/hello', '/tmp/world', (err) => {
  if (err) throw err;
  fs.stat('/tmp/world', (err, stats) => {
    if (err) throw err;
    console.log(`文件屬性: ${JSON.stringify(stats)}`);
  });
});
相關文章
相關標籤/搜索