简体   繁体   English

Node.js:如何防止两个回调同时运行?

[英]Node.js: How to prevent two callbacks from running simultaneously?

I'm a bit new to Node.js. 我对Node.js有点陌生。 I've run into a problem where I want to prevent a callback from running while it is already being executed. 我遇到了一个问题,我想阻止已执行的回调运行。 For example: 例如:

items.forEach(function(item) {
    doLongTask(item, function handler(result) {
        // If items.length > 1, this will get executed multiple times.
    });
});

How do I make the other invocations of handler wait for the first one to finish before going ahead? 如何使handler的其他调用在第一个调用完成之前等待? I'm thinking something along the lines of a queue, but I'm a newbie to Node.js so I'm not exactly sure what to do. 我正在沿着队列的方向思考,但是我是Node.js的新手,所以我不确定该怎么做。 Ideas? 想法?

How to prevent two callbacks from running simultaneously? 如何防止两个回调同时运行?

They won't run simultaneously unless they're asynchronous, because Node runs JavaScript on a single thread. 除非它们是异步的,否则它们不会同时运行,因为Node在单个线程上运行JavaScript。 Asynchronous operations can overlap, but the JavaScript thread will only ever be doing one thing at a time. 异步操作可以重叠,但是JavaScript线程一次只能做一件事。

So presumably doLongTask is asynchronous. 因此,假定doLongTask是异步的。 You can't use forEach for what you'd like to do, but it's still not hard: You just keep track of where you are in the list, and wait to start processing the next until the previous one completes: 您无法将forEach用于您想做的事情,但这并不难:您只需跟踪自己在列表中的位置,然后等待开始处理下一个,直到上一个完成为止:

var n = 0;
processItem();
function processItem() {
    if (n < items.length) {
        doLongTask(items[n], function handler(result) {
            ++n;
            processItem();
        });
    }
}

There are already libraries which take care of that, the most used being async . 已经有可以解决这个问题的库,最常用的是async

You will be interested in the async.eachSeries() function. 您将对async.eachSeries()函数感兴趣。

As for an actual example... 至于一个实际的例子...

const async = require('async')

async.eachSeries(
  items,
  (item, next) => {
    // Do stuff with item, and when you are done, call next
    // ...
    next()
  },
  err => {
    // either there was an error in one of the handlers and
    // execution was stopped, or all items have been processed
  }
)

As for how the library does this, you are better of having a look at the source code. 至于库如何执行此操作,最好查看源代码。

It should be noted that this only ever makes sense if your item handler ever performs an asynchronous operation, like interfacing with the filesystem or with internet etc. There exists no operation in Node.js that would cause a piece of JS code to be executed in parallel to another JS code within the same process. 应该注意的是,只有当您的项目处理程序执行异步操作(例如与文件系统或Internet等接口)时,这才有意义。Node.js中不存在会导致在其中执行JS代码的操作。在同一过程中与另一个JS代码并行。 So, if all you do is some calculations, you don't need to worry about this at all. 因此,如果您要做的只是一些计算,则完全无需担心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM