有一个动态值可能从小到大的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);
}
Run Code Online (Sandbox Code Playgroud)
有一些库可以帮助您组织异步代码的执行. 异步是我使用的,它的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");
}
}
);
Run Code Online (Sandbox Code Playgroud)
需要注意的是异步将尽快迭代的一个具有错误调用最终回调,所以如果你不想停在那里,你将需要调用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");
});
Run Code Online (Sandbox Code Playgroud)
注意,此代码未经过测试,可能不是最佳实现,但这就是我们使用库的原因.
我通常只使用事件发射器来使其全部同步,这样我仍然可以在异步环境思维模式下工作。在下面的代码中,每当 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()
Run Code Online (Sandbox Code Playgroud)