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

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

查看所有标签

猜你喜欢:

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

Java Concurrency in Practice

Java Concurrency in Practice

Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes、Doug Lea / Addison-Wesley Professional / 2006-5-19 / USD 59.99

This book covers: Basic concepts of concurrency and thread safety Techniques for building and composing thread-safe classes Using the concurrency building blocks in java.util.concurrent Pe......一起来看看 《Java Concurrency in Practice》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具