最近更新: 2007-05-10

TWPUG問答 - 如何偵測URL資源是否存在, Ajax way

Ka-Yue 說: JavaScript have onerror event too.

Good question. PHP 的偵測動作是在 server-side ,它可能增加 Server 不必要的網路負荷。如果改由 JavaScript 進行偵測動作,就可以把偵測動作分派給 client 去做。這是一種 Ajax 的應用。

我將使用img網頁元件進行偵測動作。可先參考《Rendering images with title and box》了解關於imgonloadonerror 的資訊。

<html>
<body>
<script type="text/javascript">
function checkUri(checkCase) {
    var uri = document.createElement('img');
    var cmdMap = {
        'success':'onload',
        'error':'onerror',
        'status':'status',
        'uri':'src'
    };
    uri.$checkCase = checkCase;
    for (var p in cmdMap) {
        uri[cmdMap[p]] = checkCase[p];
    }
}

function successHandler() {
    this.$checkCase.status = '200';
}
function errorHandler() {
    this.$checkCase.status = '404';
}

var testCaseSet = [
    {uri:'http://www.google.com.tw/intl/en_com/images/logo_plain.png'},
    {uri:'http://www.google.com.tw/intl/en_com/images/logo_plain.xxx'}
];

var initProperties = {
    'success': successHandler,
    'error': errorHandler,
    'status': null
};
for (var i = 0, checkCase; checkCase=testCaseSet[i]; ++i) {
    for (var p in initProperties)
        checkCase[p] = initProperties[p];
    checkUri(checkCase);
}

var checkTimer = window.setInterval(
    function() {
        var checkOk = true;
        for (var i = 0, checkCase; checkCase=testCaseSet[i]; ++i) {
            if (!checkCase.status) {
                checkOk = false;
                break;
            }
        }
        if (checkOk) {
            window.clearInterval(checkTimer);
            report();
        }
    },
    200
);

function report() {
    var div = document.createElement('pre');
    var msg = [];
    for (var i = 0, checkCase; checkCase=testCaseSet[i]; ++i) {
        msg.push(
            checkCase.uri +
            ': ' +
            (checkCase.status == '200' ? 'OK' : 'ERROR')
        );
    }
    div.innerHTML = msg.join('<br/>');
    document.getElementsByTagName('body')[0].appendChild(div);
}
</script>
</body>
</html>

透過 JavaScript 在 Client 進行偵測動作時,是以非同步模式運行。故程式架構會比 PHP 的同步偵測模式複雜,但效率比同步模式快上許多。

上面的例子只是精簡版。我以前寫過 Ajax 版的無效連結偵測程式[可指定並行工作線程數(threads)],輸入一個網址及指定的偵測層數後,可以從首頁往子網頁深入偵測無效連結。輸入同一個網址及同樣的探索層數, Ajax版比 PHP 版快上3-10倍有餘 (視使用者在 Ajax 版指定的並行偵測線程數而定)。

這個精簡的範例因為使用 img 實作,故有個缺點:它會把整份文件下載回 client 。如果想同 PHP 版那般只取 HEAD ,則須改用XmlHttpRequest 實現。但此時將面臨 XmlHttpRequest 的相同來源安全限制策略 (Same Origin Policy) ,故僅能偵測相同來源下之URL是否存在,用途受限。

樂多舊網址: http://blog.roodo.com/rocksaying/archives/3216885.html

樂多舊回應
tsysir@yahoo.com.tw(TyroneYeh) (#comment-10881997)
Tue, 12 Jun 2007 06:44:31 +0800
請問怎麼改成 function 化,代入網址來檢查是否存在,因為 testCaseSet 陣列如果放二十幾以上就不會動了!
謝謝
未留名 (#comment-10882473)
Tue, 12 Jun 2007 09:06:02 +0800
你需要管理多線程作業。

請參考 下載工具 Part.4 Ajax多線程管理 的示範程式 (該文最後一段)。