javascript - 事件驱动编程node.js?

标签 javascript multithreading node.js

我正在阅读这篇文章,我有一个特别的疑问是否有人向我澄清。

http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb

var fs = require('fs')
  , sys = require('sys');

fs.readFile('treasure-chamber-report.txt', function(report) {
  sys.puts("oh, look at all my money: "+report);
});

fs.writeFile('letter-to-princess.txt', '...', function() {
  sys.puts("can't wait to hear back from her!");
});

您的代码为 Node 提供了读取和写入文件的两个任务,然后进入休眠状态。一旦 Node 完成任务,就会触发它的回调。但同一时间只能触发一个回调。在该回调完成执行之前,所有其他回调都必须排队等待。除此之外,无法保证回调的触发顺序。

“所以我不必担心代码同时访问相同的数据结构?” 你说对了!这就是 JavaScript 单线程/事件循环设计的全部魅力!

  1. 谁能给我解释一下上面的粗体线条吗?为什么我们不能担心两个不同的程序无法访问该对象。
  2. 为什么当前的线程方式有问题?
  3. 回调的触发顺序会有问题吗?假设我希望callBack A() 在callBack b() 之前先返回。

最佳答案

1) 如果您运行单线程,则不必担心多线程应用程序带来的问题。这包括 2 个不同的线程尝试同时使用同一个对象。例如,想象一下,如果一个线程尝试从哈希中读取数据,而另一个线程正在从同一哈希中删除数据。键/值对可能看起来像是存在于一行代码中,但由于线程化,当它到达下一行时,数据可能不再存在。同样,您不必处理所有额外的代码和避免这些问题所涉及的麻烦。

2) 参见#1。这与其说是一个问题,不如说是一个权衡。如今,许多计算机都具有多个处理器/内核,因此让一个程序一次使用多个线程可能是有益的。当您预计线程会阻塞时,它也很有用。例如,在另一种多线程语言中,读取文件的内容并在不添加回调的情况下输出它们是很常见的。然而,这意味着线程坐在那里什么也不做(被阻塞),直到文件读取操作完成。多线程编程也很难正确完成。

3) 您不会得不到保证订单。如果您想确保顺序正确,请等待第一个调用返回后再执行第二个调用。例如

fs.readFile('treasure-chamber-report.txt', function(report) {
    sys.puts("oh, look at all my money: "+report);

    fs.writeFile('letter-to-princess.txt', '...', function() {
      sys.puts("can't wait to hear back from her!");
    });
});

请注意,这有时会让您陷入通常所说的“回调 hell ”

编辑:解决您的意见:

1) 尽管您正在“等待”NodeJS 读取文件,但在 NodeJS 中,这是一个非阻塞操作。这意味着方法调用 (readFile) 会立即返回,甚至在读取文件之前也是如此。这是因为它将数据 IO 请求传递给底层操作系统,底层操作系统有自己的线程来处理此类请求。当操作系统完成读取(或写入)时,它会通知原始进程它已准备好数据。当操作系统正在执行这项工作时,NodeJS 可以让它的一个线程在等待时继续执行其他工作。这就是为什么你需要回调 - 当你最终获得数据时,你需要一种方法来告诉 NodeJS 接下来要做什么。

2) 回调 hell 本身并没有什么坏处,只是难以阅读。人们可能会想象,如果您尝试执行的操作包括多个不同的异步进程(例如读取和写入磁盘),那么您可能会得到如下所示的结果:

var doSomething function(){
    fs.readFile('step1.txt', function(result){
        // do something with the result
        fs.writeFile('step2.txt', function(){
            // okay, step2 is ready, so process that
            fs.readFile('step2.txt', function(result){
                fs.writeFile('step3.txt', function(){
                    //etc, etc
                });
            });
        });
    });
}

您可以看到嵌套很快就会变得相当深,并且变得难以阅读。如果您搜索“JavaScript 回调 hell ”,这里和其他地方有很多讨论讨论这个问题。扁平化的一种方法是避免内联/匿名函数,并使用命名函数扁平化它,这样你的回调就不会在编辑器中嵌套得那么深(尽管从词法的 Angular 来看,嵌套仍然发生)。

关于javascript - 事件驱动编程node.js?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13365213/

相关文章:

node.js - 如何在 Redis 中的对象中搜索值?

javascript - 运行 webpack 从 npm-install-webpack-plugin 出现错误

javascript - 单击按钮可以在 iframe 中引发事件吗?

javascript - Jquery 脚本未在页面加载时执行

javascript - 检查数组长度javascript

java - 为什么主线程不能比较两个由其他线程更新的变量?

java - 如何在多个核心上执行java程序?

Android 使新的异步任务在后台或 Dropbox Core API 问题中优先于其他任务

node.js - 缩进无效,可以使用制表符或空格,但不能同时使用 jade

Javascript如何在body中添加点击事件监听器?