在 Node.JS 中应该避免循环还是有特殊的方法来处理它们?

Posted

技术标签:

【中文标题】在 Node.JS 中应该避免循环还是有特殊的方法来处理它们?【英文标题】:Should loops be avoided in Node.JS or is there a special way to handle them? 【发布时间】:2017-06-13 06:45:54 【问题描述】:

循环阻塞。他们似乎对 Node.JS 的想法漠不关心。如何处理for 循环或while 循环似乎是最佳选择的流程。

例如,如果我想打印一个直到number * 1000 的随机数表,我会想使用for 循环。在 Node.JS 中是否有一种特殊的方法来处理这个问题?

【问题讨论】:

(不是反对者)但循环在大多数情况下在 Node 中并不令人讨厌。这取决于用例,但有时异步选项更适合,有时同步操作更适合特定场景 【参考方案1】:

循环本身并不坏,但这取决于具体情况。在大多数情况下,您需要在循环中执行一些异步操作。

所以我个人的偏好是根本不使用循环,而是使用功能对应物(forEach/map/reduce/filter)。这样我的代码库就保持一致(如果需要,同步循环很容易更改为异步循环)。

const myArr = [1, 2, 3];
// sync loops
myArr.forEach(syncLogFunction);
console.log('after sync loop');

function syncLogFunction(entry) 
  console.log('sync loop', entry);


// now we want to change that into an async operation:
Promise.all(myArr.map(asyncLogFunction))
.then(() => console.log('after async loop'));

function asyncLogFunction(entry) 
  console.log('async loop', entry);
  return new Promise(resolve => setTimeout(resolve, 100));

请注意,您可以轻松地在同步和异步版本之间进行更改,结构几乎保持不变。

希望这会有所帮助。

【讨论】:

【参考方案2】:

如果你对内存中的数据进行循环(例如,你想遍历一个数组并向所有对象添加一个道具),循环将正常工作,但如果你需要在循环内做一些事情,比如保存值到数据库,你会遇到一些问题。

我意识到这不是完全正确的答案,但它是一个可能对某人有所帮助的建议。我发现处理这个问题的最简单方法之一是使用带有 forEach 的速率限制器(我不喜欢真正的承诺)。这也带来了额外的好处,即可以选择并行处理事物,但只有在一切都完成后才能继续: https://github.com/jhurliman/node-rate-limiter

var RateLimiter = require('limiter').RateLimiter;
var limiter = new RateLimiter(1, 5);

exports.saveFile = function (myArray, next) 
    var completed = 0;
    var totalFiles = myArray.length;

    myArray.forEach(function (item) 
        limiter.removeTokens(1, function () 
            //call some async function
            saveAndLog(item, function (err, result) 
                //check for errors

                completed++;

                if (completed == totalFiles) 
                    //call next function
                    exports.process();
                
            );
        );
    );
;

【讨论】:

以上是关于在 Node.JS 中应该避免循环还是有特殊的方法来处理它们?的主要内容,如果未能解决你的问题,请参考以下文章

避免对 Node.js 中的存储过程进行 SQL 注入

node.js 回调获取变量的意外值

是否应该为互斥锁获取-交换循环(或队列获取-加载循环)组合内存栅栏,还是应该避免?

Node.js 中 For 循环中的 async.waterfall

Node.js 中 For 循环中的 async.waterfall

在node.js的护照库中应该使用什么策略