检测异步队列何时完成

3
我正在将很多域名添加到async.queue(https://github.com/caolan/async)中,然后进行dns查找。由于某些原因,来自async库的drain事件过早地被调用,要么是在队列的开头,要么是很快之后。我想知道队列真正完成时的时间,以便使用结果。
如果有人可以推荐另一个库或方法来排队作业,我就不需要使用这个async库, 我只是想让它正常工作。

const dns = require('dns');
const async = require('async');
const MaxConcurrent = 2; // only do x DNS lookups at one time
const MaxWait = 1000; // wait for a second before dns timeout


var dnsQueue = async.queue(function(domain, lookupAgain) {
setTimeout(
function() {
dns.resolve(domain, function (err, address) 
{
console.log('domain: ' + domain + " address: " + address)
});
lookupAgain();
}, MaxWait);
}, MaxConcurrent);


// This should run when the queue is finished
dnsQueue.drain = function() {
console.log('done??');
}

// Array of domain names
var uniqueDomains = [
'google.com',
'yahoo.com',
'ask.com',
'cnn.com',
'real.com'
];

// Push each domain name into the dnsQueue
uniqueDomains.forEach(function(domain) {
dnsQueue.push(domain);
});

3个回答

4

如果您正在使用nodejs v7.6及以上版本,则可以尝试使用async/await。 以下是在nodejs应用程序中使用async/await的示例:

async function fun1(req, res){
  let response = await request.get('http://localhost:3000');
    if (response.err) { console.log('error');}
    else { console.log('fetched response');
}

在上面的例子中,代码要求运行代码的javascript引擎在继续执行下一行之前等待request.get()函数完成。 request.get()函数返回一个Promise,用户将等待它。在async/await之前,如果需要确保函数按照所需顺序运行,即一个接一个地链接它们或注册回调函数。
有关async/await的更多信息,请参阅以下链接:

3
我为您创建了一个异步队列系统:https://github.com/rehat101/queue.js 您不需要显式推送(push)或抽取(drain),只需运行任务,它就会为您推送(push)和刷新(flush)。如果您不关心作业何时完成,则此功能非常有用。
请尝试克隆存储库并执行以下操作:
import Queue from './src/queue';
import Promise from 'bluebird';

const { Resolver } = require('dns').promises;
const resolver = new Resolver();

let domains = [
'google.com',
'yahoo.com',
'ask.com',
'cnn.com',
'real.com'
];

(async function() {
    let queue = new Queue({concurrency: 1});
    domains.forEach(domain => queue.run(async () => {
        await Promise.delay(1000);
        console.log( await resolver.resolve(domain) );
    }));
})().catch(console.error);

您可以添加数千个作业,它会立即创建1000个未解决的承诺,但仅会在并发级别上解决这些承诺。

我计划添加更多功能并将其发布到npm上。


2
这是因为你在dns.resolve完成之前就调用了lookupAgain()。只需将lookupAgain()的位置改变即可。
const dns = require('dns');
const async = require('async');
const MaxConcurrent = 2; // only do x DNS lookups at one time
const MaxWait = 1000; // wait for a second before dns timeout


var dnsQueue = async.queue(function(domain, lookupAgain) {
  setTimeout(
    function() {
      dns.resolve(domain, function(err, address) {
        console.log('domain: ' + domain + " address: " + address)
        lookupAgain();
      });
    }, MaxWait);
}, MaxConcurrent);


// This should run when the queue is finished
dnsQueue.drain = function() {
  console.log('done??');
}

// Array of domain names
var uniqueDomains = [
  'google.com',
  'yahoo.com',
  'ask.com',
  'cnn.com',
  'real.com',
  'google.com',
  'yahoo.com',
  'ask.com',
  'cnn.com',
  'real.com'
];

// Push each domain name into the dnsQueue
uniqueDomains.forEach(function(domain) {
  dnsQueue.push(domain);
});

我已经检查过,这个工作得很好。


我尝试过这个,但不知何故,在dnsQueue.drain表示已完成后,仍然会收到MaxResult数量的结果。我以为这是异步问题(dns结果在完成后才出现),但我在drain中设置了5秒的长超时时间,仍然发生这种情况。 - direct00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接