Nodejs细节2:动手实现异步非阻塞。

Nodejs细节2:动手实现异步非阻塞。

之前想要让线程睡眠几秒在继续执行,通常采用sleep()来实现。但是这样会打破nodejs异步非阻塞的机制。效率将会大大下降。 自己实现异步 利用var childProcess = require(‘child_process’);模块,假如我们有两个js文件 1为main.js 2为sleep.js。 步骤1: 子main.js里面添加代码

//非阻塞 function sleep(millSeconds) { var subProcess = childProcess.fork(__dirname + “/subProcess.js”); subProcess.on(‘message’, function () { subProcess.kill(); emitter.emit(“RequestEvent”, null, null); //开启请求服务器事件

});
subProcess.send(sleepTime);

}

步骤2: 在sleep.js里面添加代码: /用于创建睡眠的子进程/ function sleep(milliSeconds) { var startTime = new Date().getTime(); while (new Date().getTime() < startTime + milliSeconds);

}

process.on(‘message’, function (milliSeconds) { sleep(milliSeconds); process.send({}); }); 完成,就这么简单。 process.send()可以附加很多信息。包括JSON串等


7 回复

Nodejs细节2:动手实现异步非阻塞

在Node.js中,异步非阻塞的设计理念使得它能够高效地处理I/O密集型任务。然而,有时候我们可能需要在某些操作完成后暂停执行一段时间(例如模拟一个耗时的操作),这通常使用setTimeoutsetInterval来实现。直接使用sleep()函数会让程序进入阻塞状态,这违背了Node.js的核心设计理念。

为了保持异步非阻塞特性,我们可以利用Node.js的子进程功能来实现一个简单的“睡眠”功能。这种方法通过创建一个新的子进程来处理耗时的任务,从而不会阻塞主线程。

步骤1: 创建子进程

首先,在main.js中定义一个非阻塞的睡眠函数:

const { fork } = require('child_process');

// 非阻塞的sleep函数
function sleep(milliSeconds) {
    const subProcess = fork(__dirname + "/sleep.js");
    subProcess.on('message', () => {
        subProcess.kill(); // 子进程完成后终止
        console.log("Sleep completed");
    });
    subProcess.send(milliSeconds); // 向子进程传递睡眠时间
}

// 使用sleep函数
sleep(3000); // 睡眠3秒

步骤2: 实现子进程

接下来,在sleep.js中编写处理睡眠逻辑的代码:

// sleep.js

function sleep(milliSeconds) {
    const startTime = new Date().getTime();
    while (new Date().getTime() < startTime + milliSeconds);
}

process.on('message', (milliSeconds) => {
    sleep(milliSeconds);
    process.send({}); // 向父进程发送消息表示已完成
});

解释

  1. 主进程 (main.js)

    • 使用fork方法创建一个新的子进程。
    • subProcess.on('message', callback)监听子进程的消息,当子进程完成任务后会发送消息给主进程。
    • subProcess.send(milliSeconds)将睡眠时间传递给子进程。
  2. 子进程 (sleep.js)

    • 接收从主进程传来的睡眠时间。
    • sleep函数中使用循环等待指定的时间。
    • 完成睡眠后,向主进程发送消息表示任务完成。

这种方式确保了主进程不会被阻塞,并且能够继续处理其他任务,从而充分利用了Node.js的异步非阻塞特性。


为什么不直接也 setTimeout 函数呢… … 楼主的代码还是用 Markdown 标记起来吧, 看着太辛苦了 代码开头结尾用单行加上三个反引号就可以了

好的谢谢啊

用fork来sleep,总有种高射炮打蚊子的感觉。。

请问你有什么好办法吗

setTimeout搞定。

为了更好地实现异步非阻塞操作,在Node.js中我们可以使用setTimeout或者setInterval函数,而不是通过创建子进程来模拟sleep()函数。以下是如何使用setTimeout实现异步非阻塞的示例。

示例代码

首先,我们创建一个简单的函数asyncSleep来代替传统的sleep函数:

const { EventEmitter } = require('events');

class CustomEmitter extends EventEmitter {}

const emitter = new CustomEmitter();

function asyncSleep(milliseconds) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
            emitter.emit("RequestEvent", null, null); // 开启请求服务器事件
        }, milliseconds);
    });
}

// 使用示例
asyncSleep(3000).then(() => {
    console.log("3秒后执行");
});

解释

  1. 引入EventEmitter: EventEmitter 是Node.js提供的一种用来实现观察者模式的类,可以用来触发和监听事件。

  2. 自定义事件发射器: 创建了一个继承自EventEmitter的类CustomEmitter并实例化它,以便能够触发和监听事件。

  3. 定义异步睡眠函数:

    • 定义了一个返回PromiseasyncSleep函数。
    • 当定时器超时时,使用resolve方法结束Promise,并触发一个名为"RequestEvent"的事件。
  4. 使用示例:

    • 调用asyncSleep函数并传入等待时间(毫秒),该函数会等待指定的时间后才执行后续的回调。

这种方式不仅保持了异步非阻塞特性,还能够方便地与异步编程模型(如async/await)结合使用。这种方式比创建子进程更加高效且更符合Node.js的设计理念。

回到顶部