下面有代码,我想在每次迭代的setTimeout之间放置一个Myurl。有许多classes,它们每个都包含许多元素。
//Some calculations before...
var i = 0;
async.whilst(
function () {
return i <= thefooz.length - 1;
},
function (innerCallback) {
//Some calculations where I get classes array.
async.forEachOfSeries(classes, function (Myurl, m, eachDone) {
// Here I want a delay
async.waterfall([
function (next) {
connection.query(
'SELECT * FROM mydata WHERE UrlLink=? LIMIT 1', [Myurl],
next
);
},
function (results, fields, next) {
if (results.length !== 0) {
console.log("Already Present");
return next();
}
console.log("New Thing!");
request(options2, function (err, resp, body) {
if (!err && resp.statusCode == 200) {
var $ = cheerio.load(body);
//Some calculations, where I get AllLinks.
var post = {
ThisUrl: AllLinks[0],
Time: AllLinks[1],
};
var query = connection.query('Insert INTO mydata Set ?', post, next);
};
});
}
], eachDone);
}, function (err) {
if (err) throw err;
});
setTimeout(function () {
i++;
innerCallback();
console.log("Done");
}, 20000);
//Some calculations after...那么,我如何在async.waterfall中的每个async.waterfall之间设置延迟呢?说我要延迟5秒。我设法在每个setTimeout迭代之间设置了async.whilst,但没有在每个async.forEachOfSeries迭代之间设置。它不需要等待,而是继续循环,直到每个async.forEachOfSeries完成,然后调用async.whilst setTimeout。
EDIT:队列解决方案不起作用。这个解决方案似乎只是转到下一页,下一页等等,而不是输出到我的数据库。当然,我可能会错误地应用它,但我确实试着按照示例所述的方法来做。
发布于 2015-06-10 08:05:04
我认为您不完全理解setTimeout是如何工作的:
(function () {
var seconds=0;
[1,2,3].forEach(function(value) {
setTimeout(function() {
console.log('Showing value '+value+ 'at '+Date());
},1000*seconds++);
})
})()此代码为每个元素创建一个回调函数,在第二秒钟后执行。请注意JS是单线程的,所以代码真正要做的是将“执行”添加到队列中。因此,如果当前执行不停止,则不会调用回调。因此,作为第二个参数传递给setTimeout函数的时间(在millis中)只是执行该代码的最小时间。
然后,按照FIFO顺序执行这些回调。
UPDATE:下面是我解释的一个例子:
function myFunction() {
var test=0;
setTimeout(function(){
console.log("This is the current value of test: "+test);
}, 0);
console.log("This is run first");
for (var i=0;i<50;i++) {
test++;
}
console.log("Main thread ending, not the callbacks will be executed");
} setTimeout在执行之前将等待0(零),但由于主线程尚未完成,因此无法执行。然后,当循环结束时,执行回调,发现测试为50,而不是0。
发布于 2015-06-10 08:05:11
首先,我们必须实现一个简单的队列
队列
function Queue() {
var obj = {};
var queue = [];
var _delay;
function next() {
// If queue is empty stops execution
if(queue.length == 0) return;
// Prepare next call to next
setTimeout(next, _delay);
// Take out an element from the queue and execute it.
(queue.shift())();
}
// Add a new function to the queue
obj.add = function (myFunc) {
queue.push(myFunc);
};
// Start the queue execution passing the delay between each call
obj.run = function(delay) {
_delay = delay;
// call next function
next();
}
return obj;
}然后我们在代码中使用它
// create the queue
var myQueue = Queue();
async.forEachOfSeries(classes, function (Myurl, m, eachDone) {
// Add the function to the queue
myQueue.add(executeWaterfall.bind(this));
}, function (err) {
if (err) throw err;
});
// Start the queue with 5 second delay
myQueue.run(5000);
function executeWaterfall() {
async.waterfall([
function (next) {
connection.query(
'SELECT * FROM mydata WHERE UrlLink=? LIMIT 1', [Myurl],
next
);
},
function (results, fields, next) {
if (results.length !== 0) {
console.log("Already Present");
return next();
}
console.log("New Thing!");
request(options2, function (err, resp, body) {
if (!err && resp.statusCode == 200) {
var $ = cheerio.load(body);
//Some calculations, where I get AllLinks.
var post = {
ThisUrl: AllLinks[0],
Time: AllLinks[1],
};
var query = connection.query('Insert INTO mydata Set ?', post, next);
};
});
}
], eachDone);
}这远远不是最优的,因为不管怎么说,你都掉进了所谓的“厄运金字塔”(Py金字塔of doom )。
奖金
厄运金字塔
当连续使用普通回调处理异步操作时,您将在彼此之间嵌套调用;嵌套带来了更多缩进,创建了一个金字塔(指向右侧),因此被命名为“末日金字塔”。
解决方案
在这种情况下,最好使用某种承诺模式将代码从厄运金字塔中拯救出来,并促进此类问题的解决。
发布于 2015-06-15 22:01:04
我不太熟悉async库,但在我看来,每次运行之后,async.waterfall都会调用eachdone,这样async.forEachOfSeries就知道它应该执行下一次迭代。假设eachdone是在没有参数的情况下调用的,我希望以下内容能够正常工作:
function executeWaterfall() {
async.waterfall([
......
], function () { window.setTimeout(eachDone, 5000));
}如果eachdone确实获得了参数,那么您也必须发送它们。
作为另一种选择,我希望你可以给你的瀑布再增加一步,等待5秒。这将不管eachdone的参数如何都能工作(但如果第三个瀑布函数期望有更多的副手,则可能会失败):
function executeWaterfall() {
async.waterfall([
function (next) {
connection.query(
'SELECT * FROM mydata WHERE UrlLink=? LIMIT 1', [Myurl],
next
);
},
function (results, fields, next) {
if (results.length !== 0) {
console.log("Already Present");
return next();
}
console.log("New Thing!");
request(options2, function (err, resp, body) {
if (!err && resp.statusCode == 200) {
var $ = cheerio.load(body);
//Some calculations, where I get AllLinks.
var post = {
ThisUrl: AllLinks[0],
Time: AllLinks[1],
};
var query = connection.query('Insert INTO mydata Set ?', post, next);
};
});
},
function (next) {
window.setTimeout(next, 5000);
}
], eachDone);
}现在,我想再次强调,我不熟悉async,而且所有的示例都没有经过测试。也许一切都是大错特错,但这是我的直觉。
https://stackoverflow.com/questions/30750051
复制相似问题