有一个动态值可能从小到大的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);
}
答案 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