如果顺序很重要,并且您的列表很长,并且迟早找到未访问链接的可能性很高,那么最好的方法基本上就是做您正在做的事情。这是forEachSeries
一个流行async
库的实现。
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/asyncasync
上的库的示例。
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(); });