javascript - Node.js + Express 应用程序中的并发如何工作?

标签 javascript node.js asynchronous express

(找到解决方案)

我想用代码示例开始我的问题:

var express = require('express');
var customModule = require('./custom-module');

var app = express();

// Page A
app.get('/a', function(req, res) {
    res.type('text/plain');
    customModule.doHeavyOperation(25, function(result) {
        res.send('Page A, number = ' + result);
    });
});

// Page B
app.get('/b', function(req, res) {
    res.type('text/plain');
    res.send('Page B');
});

app.listen(8082);

对于页面 A,调用 doHeavyOperation() 执行一些操作,完成后,它运行我的回调,向用户发送一些信息。

cutsom-module.js:

exports.doHeavyOperation = function(number, callback) {
    for (var i=0; i<2000000000; i++) {
        number++;
    }
    callback(number);
};

对于 doHeavyOperation() ,执行其逻辑并调用我的回调需要约 5 秒的时间。当我在浏览器中打开两个页面: localhost:8082/a 和 localhost:8082/b 时,第二个页面需要等待第一个页面加载。这意味着请求不是同时处理的。

除了 doHeavyOperation 之外,还可以有任何其他函数在我的客户端尝试使用我的 Web 应用程序时卡住我的客户端。例如,我可能想要处理用户上传的一些大图像,对其应用一些过滤器等。这可能需要 1-3 秒。所以如果有100人同时使用我的网站,就会造成很大的问题。

例如,Apache + PHP 就很好地处理了这种情况。当脚本 a.php 执行一些操作时,脚本 b.php 可以毫无问题地加载。

如何在 Node.js + Express 中实现此行为?

======================================================================================

根据 kamituel 的评论,我的决定是生成新进程来执行“繁重”计算并将结果返回给父进程。现在应用程序可以按我想要的方式工作。

我修改了我的代码:

var express = require('express');

var app = express();

// Page A
app.get('/a', function(req, res) {
    // Creating child process
    var child = require('child_process').fork('custom-module.js');
    // Sending value
    child.send(25);
    // Receiving result
    child.on('message', function(result) {
        res.type('text/plain');
        res.send('Page A, number = ' + result);
    });
});

// Page B
app.get('/b', function(req, res) {
    res.type('text/plain');
    res.send('Page B');
});

app.listen(8082);

自定义模块.js:

function doHeavyOperation(number, callback) {
    for (var i=0; i<2000000000; i++) {
        number++;
    }
    callback(number);
};

process.on('message', function(number) {
    doHeavyOperation(number, function(result) {
        process.send(result);
    });
});

有关 child_process 的更多信息 here .

最佳答案

Javascript(Node.js 也是如此)使用一个主线程来处理(几乎)您编写的所有 JS 代码。这意味着如果您有一些长时间运行的任务(例如示例中的巨大循环),则该任务将阻止其他代码(即回调)的执行。

对此你能做什么?

  • 将循环分成更小的部分,并偶尔产生控制(即使用 setTimeout/nextTick 或类似的)。 IE。您可以从 0 迭代到 1000,然后在下一个刻度上执行接下来的 1000 次循环迭代,依此类推。
  • 生成一个新进程并在那里处理繁重的任务。由于新进程将位于 Node.js 本身之外,因此不会阻止它。

关于javascript - Node.js + Express 应用程序中的并发如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26547431/

相关文章:

javascript - 从 IMG SRC 中删除第一个正斜杠

javascript - 如何延迟显示页面内容直到页面完全加载(包括脚本和样式)

wp header 内的 javascript 幻灯片无法正常工作

node.js - API.ai/Dialogflow 基本文本请求不起作用

javascript - 如何去掉javascript中的注释?

asyncsocket - 在所有情况下都必须调用 EndRead() 吗?

javascript - Selenium IDE - 选择OkOnNextConfirmation 而不使用assertConfirmation?

javascript - 无法获得 sequelize findbyPk 以向我的 React 应用程序返回单个值

javascript - JavaScript 中的调试技术。异步回调

c# - 这种方法能达到100%的代码覆盖率吗?