如何从特定功能节点js

时间:2019-07-12 03:18:01

标签: javascript node.js events

我有一个公共事件发射器。

var events = require('events');
var eventEmitter = new events.EventEmitter();

发出诸如暂停,恢复,取消之类的事件。

我在我的函数中收听此事件。但是此函数在for循环内部调用。

let func = () =>{
   //some Action runs async;
   eventEmitter.on("pause",()=>{
     //some action;
   });
   eventEmitter.on("resume",()=>{
     //some action;
   }) 
  eventEmitter.on("cancel",()=>{
     //some action;
   }) 
  return 0;
}

for(let i=0;i<anyNumber;i++){
   func();
}

编辑:我真正的缩进是递归地读取目录中的文件并上传到s3 Bucket,因为没有官方的方法可以上传整个目录,因此我做到了。

上面提到的for循环实际上是fs.readdir,为简单起见,我将其称为for循环。

在func()中,我具有s3上传功能(分段上传),同时单击了暂停按钮,我需要暂停上传(这意味着已经保留了当前部分的上传,并停止了另一部分的上传。)

“恢复”表示继续部分上传,而“取消”表示我取消分段上传。

这是我的确切情况。

const readdirp = require('readdirp');
readdirp('.', {fileFilter: '*.js', alwaysStat: true})
 .on('data', (entry) => {
  const {path, stats: {size}} = entry;
  s3Fileupload(path)
})
.on('warn', error => console.error('non-fatal error', error))
.on('error', error => console.error('fatal error', error))
.on('end', () => console.log('done'));

您现在可以帮我吗?

EDIT:1

let func = () =>{
 let stream = es.map((data, next) => {
  queue.defer(function(details, done) {
    _this.s3MultiUpload(JSON.parse(details), options, done, details, next);
  }, data);
}); }
let stream = readdirp(path)
stream.pipe(this.func());

可能是我在这里使用的d3Queue可能导致内存泄漏,我在读取目录时一直将函数推入整个过程?

1 个答案:

答案 0 :(得分:1)

要删除侦听器,请致电eventEmitter.removeListener(event, listener)。 您需要保留所有侦听器的副本。 另外,如果没有在其他地方使用发射器,则可以简单地调用eventEmitter.removeAllListeners()

  

如果我这样做,那之后我不能听那个事件了吗?

你是对的。您需要等待,直到不再需要该事件,然后将其删除。

理想情况下,您不想附加太多的侦听器。 无需增加限制,而是在单个事件回调中完成所有工作。

这是我要怎么做:

// Create an event emitter
const events = require('events');
const eventEmitter = new events.EventEmitter();

// Build a list of tasks to run
let tasks = [];
let tasksDone = 0;
for (let file of files) {
    // Each task can be paused, resumed, canceled
    let task = tasks.push({
        pause: () => {/* TODO */},
        resume: () => {/* TODO */},
        cancel: () => {/* TODO */},
        start: async () => {
            // Do work
            // Send a signal when task is done
            eventEmitter.emit('done');
        }
    });
    tasks.push(task);
}

// Store the listeners
let listeners = [
    ['pause', () => {
        tasks.forEach(task => task.pause());
    }],
    ['resume', () => {
        tasks.forEach(task => task.resume());
    }],
    ['cancel', () => {
        tasks.forEach(task => task.cancel());
    }],
    ['done', () => {
        tasksDone++;
        if (tasksDone === task.length) {
            // All work done
            // Remove listeners
            listeners.forEach(([event, callback]) => {
                eventEmitter.removeListener(event, callback);
            });
        }
    }],
];

// Attach listeners
listeners.forEach(([event, callback]) => {
    eventEmitter.on(event, callback);
});

// Start tasks
tasks.forEach(task => task.start());

尽管如此,您的应用程序可能由于其他原因而崩溃。 如果您同时打开太多文件或使用太多内存,则在完成任务之前,应用程序可能会崩溃。不用说,您还应该确保文件已关闭等。

我建议先对任务进行排队,然后一次完成一个任务。 如果需要更高的吞吐量,请编写一个调度程序以确保您一次不会消耗太多资源。

最后,对于节点程序,您可以连接Chrome调试器以找出为什么不释放内存的原因。如果问题仍然存在,您可以确切地找到导致内存中断的原因。