如何阻止功能,直到前一个功能完成?的NodeJS

时间:2013-07-29 23:50:21

标签: node.js

有一个动态值可能从小到大的for循环,我想确保在下一个调用开始之前完成一次搜索调用。我怎么做?我已经阅读了有关process.nextTick和setImmediate的内容,但我不确定如何在此上下文中使用它。

function search(x) {
      dns.resolve(x, function (err, addresses) {
           if (!err) {
                res.send("bad");
           } else {
                res.send("good");
           }
      });
}

for(a = 0; a < queries.length; a++) {
    query = queries[a];
    search(query);
}

3 个答案:

答案 0 :(得分:6)

有一些库可以帮助您组织异步代码的执行。 Async是我使用的,eachSeries()在这里很有用:

function search(x,callback) {
  dns.resolve(x, function (err, addresses) {
    if (!err) {
      res.send("bad");
    } else {
      res.send("good");
    }
    callback(err);
  });
}

async.eachSeries(queries,
  function(query,callback) {
    search(query,callback);
  },
  function(err) {
    if(err) {
      console.log("we had an error");
    }
  }
);

请注意,只要其中一个迭代出现错误,Async就会调用最终回调,因此如果您不想停在那里,则需要在callback()中调用search()而不是callback(err)

更新(不使用库):

如果您不想使用库,可以像下面这样自己实现:

function searchInternal(queries, idx, callback) {
  if(idx === queries.length) {
    callback();
    return;
  }

  dns.resolve(queries[idx], function (err, addresses) {
    if (!err) {
      res.send("bad");
    } else {
      res.send("good");
    }
    searchInternal(queries, idx+1, callback);
  });
}

function searchAll(queries, callback) {
  searchInternal(queries, 0, callback);
}

searchAll(queries, function() {
  console.log("all done now");
});

请注意,此代码未经过测试,可能不是最佳实现,但这就是我们使用库的原因。

答案 1 :(得分:3)

我通常只使用事件发射器使它全部同步,所以我仍然可以在异步环境思维模式下工作。在下面的代码中,每当DNS解析完成时,它会生成一个由搜索功能监听的事件,并让它知道触发新的搜索。此外,您还可以学习如何创建自己的事件发射器,这非常棒。

如果要使其与某个大小的域名数组异步,可以创建一个分母变量并使用模数运算符以块的形式发送异步,并且只在每次触发同步事件(以清除异步缓冲区)时模数达到0。

// program that uses event emitters to create sync code in an async env

var dns = require('dns')                                //dns from core
var eventEmitter = require('events').EventEmitter       //Event Emitter from core

var ee = new eventEmitter;      //make an Event Emitter object

var queries = ['yahoo.com','google.com','james.com'];

ee.on('next', next_search);     //create a listener for an event we define

// our listening function that executes on our defined 'next' event
function next_search() {
        search(queries[a]);
        if(queries.length == a) process.exit(0);
        ++a;
}

// the actual search function that uses DNS
function search(x) {
        dns.resolve(x, function (err) {
                if (!err) {
                        //res.send("bad");
                        console.log('bad: ' + x)
                        ee.emit('next')
                } else {
                        //res.send("good");
                        console.log('good: ' + x)
                        ee.emit('next')
                }
        });
}


// global variable to keep track of our name queue length
var a = 0;

// kick it all off
next_search()

答案 2 :(得分:2)

我最近创建了一个名为 wait.for 的简单抽象来在同步模式下调用异步函数(基于节点光纤)。它在:

https://github.com/luciotato/waitfor

使用 wait.for ,您可以调用dns.resolve来按顺序执行。

wait.for 允许您调用任何标准nodejs异步函数,就像它是同步函数一样,没有阻塞节点的事件循环。您可以在需要时按顺序编码。

使用 wait.for 您的代码将是:

for(a = 0; a < queries.length; a++) {
  try {
    addresses = wait.for(dns.resolve,queries[a]);
    res.send('good');
  }
  catch(err){
    res.send('bad');
  }

}//end for