Javascript 在主线程期间执行的异步任务

Javascript 在主线程期间执行的异步任务,javascript,node.js,Javascript,Node.js,JavaScript是一种单线程编程语言(一次可以完成一项任务) 因此,它首先运行主线程(同步),然后在事件循环中执行异步任务(这是我理解的,但显然我错了) js使用libuv库来处理异步任务 // synchronously open file descriptor var fd = fs.openSync('testFile', 'r+'); // synchronously write data to the file fs.writeSync(fd, ' first data par

JavaScript是一种单线程编程语言(一次可以完成一项任务)

因此,它首先运行主线程(同步),然后在事件循环中执行异步任务(这是我理解的,但显然我错了)

js使用libuv库来处理异步任务

// synchronously open file descriptor
var fd = fs.openSync('testFile', 'r+'); 

// synchronously write data to the file
fs.writeSync(fd, ' first data part '); 

// asynchronously write data to the file
fs.write(fd, ' second data part ', function(err){ 
    if(err) console.log( err );
});

// asynchronously close the file descriptor 
fs.closeSync(fd);
异步写入方法成功地将数据写入文件,但并非总是如此!(方法抛出错误“错误的文件描述符”)

我预期异步“write()”方法会出错,因为文件描述符是同步关闭的,因此它不应该有有效的文件描述符(但情况并非如此,至少不总是如此)

这里有一些问题

  • 这是否意味着异步任务由运行单独JS线程的libuv单独执行,从而不会导致上述示例崩溃

  • 如果我正好在上面,这是浏览器中的相同行为吗(浏览器之间是否存在异步差异?)

  • 如果我错了,上面的异步“write()”方法是如何获取文件描述符的

这是否意味着异步任务由运行单独JS线程的libuv单独执行,从而不会导致上述示例崩溃

不是一个JavaScript线程,不是。Node.js在一个独立的非JavaScript线程上运行I/O任务-但更重要的是,它尽可能使用操作系统的异步I/O功能,以避免不必要地捆绑该线程/那些线程。这些特性允许它在该线程/其他线程上排队并处理I/O进度/完成,然后在主JavaScript线程的事件循环上适当地排队调用异步函数的回调(在本例中,是您的
write
回调)


因此,代码中存在的是未协调的线程之间的竞争,这解释了为什么有时它可以工作,而有时它会失败。由于操作系统级别涉及的所有因素,线程调度似乎是不确定的。

JavaScript在某种程度上是单线程的。JS的并发风格被称为非阻塞。代码是在一个线程(事件循环)上执行的,因此您不能阻止它或所有事情都停止(这就是为什么警报会阻止您与页面交互),但在引擎盖下,浏览器有用于AJAX请求、渲染、事件触发器和文件操作的线程。当他们捕获任何新事件时,会将其推送到事件队列中,然后触发代码运行的事件循环,并处理请求。

这是Node.js,不是浏览器。