如果订单很重要,而且您的清单很长,并且较晚找到未访问链接的可能性很高,那么最好的方法就是基本上做您正在做的事情。这是来自流行的async
库的forEachSeries
实现。
async.forEachSeries = function (arr, iterator, callback) {
callback = callback || function() {};
if (!arr.length) {
return callback();
}
var completed = 0;
var iterate = function() {
iterator(arr[completed], function (err) {
if (err) {
callback(err);
callback = function() {};
}
else {
completed += 1;
if (completed === arr.length) {
callback(null);
}
else {
iterate();
}
}
});
};
iterate();
};
你会看到你已经开始实现的相同的递归模式。另一种选择是将它们全部平行并在追回时跟踪它们。只要列表中的第一个项目以未访问的方式返回,您可以立即退出。注意:下面的代码是未经测试...
var urls = [a,b,c,d],
unvisitedUrls = [],
count = urls.length,
done = false;
var checkUrl = function(d) {
var url = d;
return function(visitItems) {
if (done) return;
count--;
if (visitItems && visitItems.length > 0) {
unvisitedUrls.push(url);
}
else {
urls.splice(urls.indexOf(url)); // remove the visited url
}
if(unvisitedUrls.indexOf(urls[0]) > -1 || count === 0) {
done = true;
// done checking urls, urls[0] is the winner
}
}
}
urls.forEach(function(d) { chrome.history.getVisits(d, checkUrl(d)); });
如果你的列表是数以百万计的项目长,那么你可以通过他们分批,而不是一次全部迭代。以下是使用在https://github.com/caolan/async处找到的async
库的示例。
var checkUrl = function(url, cb) {
chrome.history.getVisits(url, function(itemVisits) {
if (done) return cb();
count--;
if (visitItems && visitItems.length > 0) {
unvisitedUrls.push(url);
}
else {
urls.splice(urls.indexOf(url)); // remove the visited url
}
if(unvisitedUrls.indexOf(urls[0]) > -1 || count === 0) {
done = true;
// done checking urls, urls[0] is the winner
}
cb();
}
};
async.forEachLimit(urls, 50, checkUrl, function(err) { doSomethingWithWinner(); });
因此,这将检查(可能长)列表中的每个URL。你什么时候找到哪一个是_first_?你想如何,直到检查之前的所有内容都被检查过,以便你知道它确实是第一个? – Chuck 2012-10-23 03:43:47
列表多长时间?你首先考虑什么?首先根据您的原始URL列表? – Bill 2012-10-23 03:45:36
是的 - 原始问题说我想查找列表中的第一个未访问的URL。同样,它表示担心递归方法会导致堆栈溢出(因此,一个大列表) – Chuck 2012-10-23 03:47:14