【问题标题】:Blocking function in node.js applicationnode.js 应用程序中的阻塞函数
【发布时间】:2017-03-17 17:12:34
【问题描述】:

我正在创建一个 node.js 应用程序。它的功能之一是上传一个excel文件,然后读取它并将其内容保存在数据库中。问题是我是node.js的新手,我不理解非阻塞代码的概念,所以这个函数似乎阻塞了主线程,所以我需要一些帮助来解决这个问题。

app.post('/admin/upload_file', function(req, res) {
    var sampleFile;
    if (!req.files) {
        res.send('No files were uploaded.');
        console.log('No files were uploaded.');
        return;
    }
    sampleFile = req.files.sampleFile;
    var fileArray = sampleFile.name.split('.');
    var extension = fileArray[fileArray.length - 1];
    if (extension == "xlsx") {
        sampleFile.mv('./public/uploads/sample_file.xlsx', function(err) {
            if (err) {
                res.status(500).send(err);
            } else {
                var entries = parsing_file(req, res);
                if (entries.length > 0) {
                    for (var i = 0; i < entries.length; i++) {
                        // this loop on database queries block the main thread
                        model.insert_in_db(entries[0], function(rows) {});
                    }
                }
                res.redirect('/admin');
            }
        });
    } else {
        res.redirect('/admin');
  }
});

parsing_file 函数解析文件并将值作为对象存储到数组中,当数据库查询上的循环(负责将值插入数据库)作为节点的主线程开始时,问题就开始了.js 被阻塞,直到循环完成它的工作。

【问题讨论】:

    标签: javascript node.js multithreading asynchronous


    【解决方案1】:

    使用 fs.readFile 从文件中读取数据它是异步操作并使用 async.eachLimit 而不是 for 循环它是非阻塞异步操作而 for 循环如果同步操作

     fs.readFile('./public/uploads/sample_file.xlsx', function (err, data) {
            if (err) {
                res.status(500).send(err);
            } else {
                var entries = parsing_file(req, res);                
                if (entries.length > 0) {
                    async.eachLimit(entries, 10, function(entrie, callback){                      
                        model.insert_in_db(entrie, function(rows) {callback()});
                    },function(err){
                          if( err ) {
                             // One of the iterations produced an error.
                             // All processing will now stop.
                             console.log('A file failed to process');
                          } else {
                              console.log('All files have been processed 
                              successfully');
                              return res.redirect('/admin');
                          }
                   })                
            }           
      });
    

    阅读https://caolan.github.io/async/docs.html#eachLimit async 文档了解更多详情。

    【讨论】:

    • 这正是我正在寻找的,特别是关于async.eachLimit 的部分,但你知道,设置限制数量的最佳做法是什么?还是取决于完成查询所需的时间?
    • async.leachLimit 用于设置一次异步操作的最大数量。由于 eachlimit 并行运行,因此如果有数千条记录要保存到循环中,则节点调用堆栈将已满并抛出错误调用堆栈限制已达到。所以为了避免这种情况,我们使用limit来并行运行有限的记录,然后在执行循环之后并行运行下一个记录。限制数量取决于你在 eachLimit 函数中的逻辑,你在那里做什么。
    【解决方案2】:

    TL;DR 我不知道insert_in_db方法的实际实现是什么,但它似乎是一个同步方法。在这种情况下,您的代码实际上被该方法阻止了。

    但是,在我看来,在数据库中编写异步代码并不是一个好主意,以避免与同时访问同一记录相关的问题。

    简而言之,如果该方法被阻塞,那肯定是有原因的。

    【讨论】:

      猜你喜欢
      • 2017-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 1970-01-01
      • 2020-03-29
      • 2015-07-06
      相关资源
      最近更新 更多