使用events.EventEmitter 控制Node.js 程序执行流程

使用events.EventEmitter 控制Node.js 程序执行流程html

标题写的可能也不太对,你们领会精神;node

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

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

 

Node.js 异步编程的直接体现就是回调。设计模式

异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。数组

回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 全部 API 都支持回调函数。并发

例如,咱们能够一边读取文件,一边执行其余命令,在文件读取完成后,咱们将文件内容做为回调函数的参数返回。异步

这样在执行代码时就没有阻塞或等待文件 I/O 操做。这就大大提升了 Node.js 的性能,能够处理大量的并发请求。异步编程

 

Node.js 是单进程单线程应用程序,可是由于 V8 引擎提供的异步执行回调接口,经过这些接口能够处理大量的并发,因此性能很是高。函数

Node.js 几乎每个 API 都是支持回调函数的。

Node.js 基本上全部的事件机制都是用设计模式中观察者模式实现。

Node.js 单线程相似进入一个while(true)的事件循环,直到没有事件观察者退出,每一个异步事件都生成一个事件观察者,若是有事件发生就调用该回调函数。

大意就是说:与大多数 代码从上至下线性执行的 程序不一样,Node.js 程序不会“等”,

当程序执行到须要I/O执行时间的回调函数时,会主动略过等待,继续执行下面的代码;

所以就会出现一种弊端:一个特定函数的输入(参数),是数个回调函数的返回;

程序的执行机制会略过 对回调函数的等待,直接执行下面的特定函数;此时特定函数并无等到回调函数返回的输入;

例子以下:

var fs = require("fs");
var array = [1, 2, 3, 4, 5]; var json = {};
for (let index = 0; index < array.length; index++) { const element = array[index]; deal(element, function (ret) { json[element] = ret; console.log(json); }); } console.log(json); function deal(num, callback) { fs.readFile(num + '.txt', function (err, data) { if (err) { console.error(err); callback(err); } else { callback(data.toString().trim()); } }); } Object {} Object {1: "11111"} Object {1: "11111", 5: "55555"} Object {1: "11111", 3: "33333", 5: "55555"} Object {1: "11111", 3: "33333", 4: "44444", 5: "55555"} Object {1: "11111", 2: "22222", 3: "33333", 4: "44444", 5: "55555"}

回调函数要以数组里的内容做为文件名,读取文件中的数据做为返回值;

但程序不会等待文件读取完成,在没有一个文件读取完毕的状况下就执行了打印操做,输出了空对象;

若是想要按顺序线性执行文件读取,在读取完毕后打印输出,不只浪费时间,并且一层套一层代码冗余,

还没法预估数组大小(回调函数个数)。

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

解决的办法是:Node.js 的事件驱动特性,让打印做为一个事件,在全部的回调函数执行完后,再触发打印操做;

var fs = require("fs");
var events = require('events'); 
var emitter = new events.EventEmitter(); 

var array = [1, 2, 3, 4, 5];
var count = 0;
var json = {};

for (let index = 0; index < array.length; index++) {
    const element = array[index];
    deal(element, function (ret) {
        json[element] = ret;
        console.log(json);
    });
}

emitter.on('dataBack', function() { 
    count ++;
    if(count == array.length){
        console.log(json);
    }
}); 

function deal(num, callback) {
    fs.readFile(num + '.txt', function (err, data) {
        if (err) {
            console.error(err);
            callback(err);
            emitter.emit('dataBack'); 
        } else {
            callback(data.toString().trim());
            emitter.emit('dataBack'); 
        }
    });
}


Object {1: "11111"}
Object {1: "11111", 4: "44444"}
Object {1: "11111", 3: "33333", 4: "44444"}
Object {1: "11111", 3: "33333", 4: "44444", 5: "55555"}
Object {1: "11111", 2: "22222", 3: "33333", 4: "44444", 5: "55555"}
Object {1: "11111", 2: "22222", 3: "33333", 4: "44444", 5: "55555"}

在程序中添加打印事件和事件触发,所有数据都集齐后再打印,

虽然还有count的锁不锁的问题存在,但实际的问题已然解决;

嗯嗯。

 

引用和改写的程序都来源于 Node.js 教程 | 菜鸟教程

Node.js 文件系统 | 菜鸟教程

Node.js EventEmitter | 菜鸟教程

 

 

 

不不不,一点也不推荐你们这么用。。。

太low了 用Promise吧

function run_a(num) {
  return new Promise(function (resolve, reject) {
    if (!isNaN(num)) {
      resolve({ "number": num, "10*num": 10 * num })
    } else {
      reject({ "error": num + " is not a number!" })
    }
  });
}

var array = [1, 2, 3, 4, 5, 6, 7];
var function_array = [];
array.forEach(element => {
  function_array.push(run_a(element));
});
console.log(function_array); // Array(7) [Promise, Promise, Promise, Promise, Promise, Promise, Promise]

Promise.all(function_array).then(function (data) {
  console.log(JSON.stringify(data));
  // [{"number":1,"10*num":10},{"number":2,"10*num":20},{"number":3,"10*num":30},{"number":4,"10*num":40},
  // {"number":5,"10*num":50},{"number":6,"10*num":60},{"number":7,"10*num":70}]
}, function (data) {
  console.log(data);
});
var array = [1, 2, 3, 4, 5, 'a', 7];
var function_array = [];
array.forEach(element => {
  function_array.push(run_a(element));
});

Promise.all(function_array).then(function (data) {
  console.log(JSON.stringify(data));
}, function (data) {
  console.log(data); // {error: "a is not a number!"}
});

Promise的用法简单入门_慕课手记

用Promise应对这种未知次数的并发等待问题能够说是很合适的了。

 

 

 

 

                                                                                                                                                                                            J.X.Duasonir

相关文章
相关标签/搜索