順序が重要で、リストが長く、未訪問のリンクをすぐに見つける可能性が高い場合、基本的に最善の方法は、実行していることを実行することです。これが人気のあるライブラリからの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();
};
実装を開始したのと同じ再帰パターンが表示されます。もう1つのオプションは、すべてを並行して開始し、戻ってきたときに追跡することです。リストの最初のアイテムが未訪問として戻ってきたらすぐに終了できます。注:次のコードはテストされていません...
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(); });