Node.js基础 23456:全局对象,回调函数,模块,事件,读写文件(同步,异步)

栏目: Node.js · 发布时间: 5年前

内容简介:全局变量在所有模块中都可使用。 以下变量虽然看起来像全局变量,但实际上不是(global里面没有以下属性)。 它们的作用域只在模块内,详见 文档:与js一样,如:一个大项目一定是分成一个个模块的,一般来说,一个文件就是一个模块。

全局对象

类似的,在浏览器中有 window

全局变量在所有模块中都可使用。不需要引用等。

全局变量

console , setTimeout , require()

全局变量在所有模块中都可使用。 以下变量虽然看起来像全局变量,但实际上不是(global里面没有以下属性)。 它们的作用域只在模块内,详见 文档:

__dirname
__filename
exports
module
require()

回调函数

与js一样,如:

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

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

模块

一个大项目一定是分成一个个模块的,一般来说,一个文件就是一个模块。

模块使用方法:

Node.js基础 23456:全局对象,回调函数,模块,事件,读写文件(同步,异步)

向外暴露的是一个对象。

Node.js基础 23456:全局对象,回调函数,模块,事件,读写文件(同步,异步)

我们 require() 的时候,接收的也是一个对象.

所以也可以这样写:

Node.js基础 23456:全局对象,回调函数,模块,事件,读写文件(同步,异步)

Node.js基础 23456:全局对象,回调函数,模块,事件,读写文件(同步,异步)

app.js

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.html

大多数 Node.js 核心 API 构建于惯用的异步事件驱动架构,其中某些类型的对象(又称触发器,Emitter)会触发命名事件来调用函数(又称监听器,Listener)。

例如, net.Server 会在每次有新连接时触发事件, fs.ReadStream 会在打开文件时触发事件, stream 会在数据可读时触发事件。

所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上。 事件的命名通常是驼峰式的字符串。

EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都会被同步地调用。

例子,一个简单的 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')

Node.js基础 23456:全局对象,回调函数,模块,事件,读写文件(同步,异步)

总结:

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming in Haskell

Programming in Haskell

Graham Hutton / Cambridge University Press / 2007-1-18 / GBP 34.99

Haskell is one of the leading languages for teaching functional programming, enabling students to write simpler and cleaner code, and to learn how to structure and reason about programs. This introduc......一起来看看 《Programming in Haskell》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具