0

Chrome 拡張機能の URL (配列) のリストから、まだアクセスされていないすべてのリンクをリストしようとしています。しかし、以下の関数は 1 つの URL のみを返します。私はどこで間違っていますか?

function remove_visited(urls, fn) {
    var links = urls,
    unvisitedUrls = [],
    done = false;
    console.log(urls);

    var checkUrl = function(d) {
        var url = d;
        console.log(url);
        return function(visitItems) {
            if (visitItems && visitItems.length > 0) {
                unvisitedUrls.push(url);
            }
            links.splice(links.indexOf(url));
            if(links.length <= 0) {
                return;
            }
        }
    }

    links.forEach(function(d) {
        chrome.history.getVisits(d, checkUrl(d));
    });

    fn(links);
}

参照:非同期 chrome.history 呼び出しのラングリング

4

1 に答える 1

3

非同期呼び出しの意味 (および内部の仕組み) を誤解している可能性があります。

次のアプローチを提案します。

  1. URL のリストと、未訪問の URL のリストを引数として実行するコールバックを提供します (すべての URL の履歴チェックが完了した後)。


  2. 元のリストの各 URL について: アクセスされているかどうかを確認します (アクセスされている場合は、未アクセスの URL のリストに追加します)。
    b. checkedURLsカウンターをインクリメントします。
    c. すべての URL が (非同期に) チェックされているかどうかをチェックします。つまりcheckedURLs、元の URL リストの長さと同じです。

  3. すべての URL がチェックされたことを検出したら ( 2.c.を参照)、指定されたコールバックを実行し ( 1.を参照)、未訪問の URL のリストを引数として渡します。


デモ拡張機能のサンプル コード:

マニフェスト.json:

{
    "manifest_version": 2,
    "name":    "Demo",
    "version": "0.0",

    "background": {
        "persistent": false,
        "scripts": ["background.js"]
    },
    "browser_action": { "default_title": "Demo Extension" },
    "permissions": ["history"]
}

background.js:

/* List of URLs to check against */
var urlList = [
    "http://stackoverflow.com/",
    "http://qwertyuiop.asd/fghjkl",
    "https://www.google.com/",
    "https://www.qwertyuiop.asd/fghjkl"
];

/* Callback to be executed after all URLs have been checked */
var onCheckCompleted = function(unvisitedURLs) {
    console.log("The following URLs have not been visited yet:");
    unvisitedURLs.forEach(function(url) {
        console.log("    " + url);
    });
    alert("History check complete !\n"
          + "Check console log for details.");
}

/* Check all URLs in <urls> and call <callback> when done */
var findUnvisited = function(urls, callback) {
    var unvisitedURLs = [];
    var checkedURLs = 0;

    /* Check each URL... */
    urls.forEach(function(url) {
        chrome.history.getVisits({ "url": url }, function(visitItems) {
            /* If it has not been visited, add it to <unvisitedURLs> */
            if (!visitItems || (visitItems.length == 0)) {
                unvisitedURLs.push(url);
            }

            /* Increment the counter of checked URLs */
            checkedURLs++;

            /* If this was the last URL to be checked, 
               execute <callback>, passing <unvisitedURLs> */
            if (checkedURLs == urls.length) {
                callback(unvisitedURLs);
            }
        });
    });
}

/* Bind <findUnvisited> to the browser-action */
chrome.browserAction.onClicked.addListener(function() {
    findUnvisited(urlList, onCheckCompleted);
});
于 2013-10-27T09:30:45.407 に答える