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串等
Nodejs细节2:动手实现异步非阻塞
在Node.js中,异步非阻塞的设计理念使得它能够高效地处理I/O密集型任务。然而,有时候我们可能需要在某些操作完成后暂停执行一段时间(例如模拟一个耗时的操作),这通常使用setTimeout
或setInterval
来实现。直接使用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({}); // 向父进程发送消息表示已完成
});
解释
-
主进程 (
main.js
)- 使用
fork
方法创建一个新的子进程。 subProcess.on('message', callback)
监听子进程的消息,当子进程完成任务后会发送消息给主进程。subProcess.send(milliSeconds)
将睡眠时间传递给子进程。
- 使用
-
子进程 (
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秒后执行");
});
解释
-
引入EventEmitter:
EventEmitter
是Node.js提供的一种用来实现观察者模式的类,可以用来触发和监听事件。 -
自定义事件发射器: 创建了一个继承自
EventEmitter
的类CustomEmitter
并实例化它,以便能够触发和监听事件。 -
定义异步睡眠函数:
- 定义了一个返回
Promise
的asyncSleep
函数。 - 当定时器超时时,使用
resolve
方法结束Promise,并触发一个名为"RequestEvent"
的事件。
- 定义了一个返回
-
使用示例:
- 调用
asyncSleep
函数并传入等待时间(毫秒),该函数会等待指定的时间后才执行后续的回调。
- 调用
这种方式不仅保持了异步非阻塞特性,还能够方便地与异步编程模型(如async/await
)结合使用。这种方式比创建子进程更加高效且更符合Node.js的设计理念。