Description
CDN Search
75CDN BootCDN
<!DOCTYPE html>
<html>

<head>
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<meta charset="utf-8" />
	<meta name="referrer" content="never">
	<title>NetnrRun</title>
</head>

<body>
	<h4>请打开控制台或按F12</h4>
	<button id="btn1">可用的源</button>
	<button id="btn2">最快的源</button>
	<button id="btn3">自定义超时</button>
	<button id="btn4">获取天气</button>
	<div id="result"></div>
</body>

</html>
/*
    upstream: From nginx upstream
    - Source must support cross-domain
    v1.0.0
    2019-04-02
    https://github.com/netnr/upstream
 */
(function (window) {
    var ups = function (hosts, callback, timeout) {
        window.upstreamCache = window.upstreamCache || {};
        //10秒内缓存
        var startTime = new Date().valueOf(), cacheKey = hosts.join(','),
            hostsCache = window.upstreamCache[cacheKey];
        if (hostsCache && startTime - hostsCache.date < 10000) {
            callback(hostsCache.ok[0], hostsCache.ok);
        } else {
            var ok = [], bad = 0, i = 0, len = hosts.length;
            for (; i < len;) {
                var host = hosts[i++];
                //自动补齐链接
                host = host.trim().toLowerCase().indexOf("//") >= 0 ? host : "//" + host;
                //发起fetch,添加成功的url(该url与hosts可能不一样),须支持跨域请求
                fetch(host).then(function (res) {
                    res.ok ? ok.push(res.url) : bad++;
                }).catch(() => bad++)
            }
            var si = setInterval(function () {
                var isc = false, now = new Date().valueOf();
                //当timeout为1,返回最快可用的host
                if (timeout == 1 && ok.length > 0) {
                    isc = true;
                }
                //所有请求结束 或 超时(默认3000毫秒),返回结果
                var istimeout = now - startTime > ((timeout == 1 || !timeout) ? 3000 : timeout);
                if (ok.length + bad == len || istimeout) {
                    isc = true;
                }
                if (isc) {
                    clearInterval(si);
                    window.upstreamCache[cacheKey] = { date: now, ok: ok };
                    callback(ok[0], ok);
                }
            }, 1)
        }
    }

    window.upstream = ups;

    return ups;
})(window);


//示例
var hosts = ["proxy.zme.ink", "bird.ioliu.cn/v2?url=", "api.github.com"];

document.getElementById("btn1").onclick = function () {
    upstream(hosts, function (fast, ok) {
        console.log(fast, ok)
        log(fast, ok)
    });
}

document.getElementById("btn2").onclick = function () {
    upstream(hosts, function (fast, ok) {
        console.log(fast, ok)
        log(fast, ok)
    }, 1);
}

document.getElementById("btn3").onclick = function () {
    upstream(hosts, function (fast, ok) {
        console.log(fast, ok)
        log(fast, ok)
    }, 280);
}

document.getElementById("btn4").onclick = function () {
    upstream(["https://proxy.zme.ink/", "https://bird.ioliu.cn/v2?url="], function (fast) {
        var api = "http://wthrcdn.etouch.cn/weather_mini?citykey=101040100";
        var url = fast + api;
        fetch(url).then(res => res.json()).then(function (data) {
            console.log(data);
            log(data);
        });
    }, 1);
}

function log() {
    var ret = document.getElementById("result");
    for (var i = 0; i < arguments.length; i++) {
        var msg = arguments[i];
        if (typeof msg != "string") {
            msg = JSON.stringify(msg);
        }
        var pre = document.createElement("pre");
        pre.innerHTML = msg;
        ret.appendChild(pre);
    }
    ret.appendChild(document.createElement("hr"))
    ret.scrollTo(0, 9999999);
}
#result{
    color:#fff;
    overflow: auto;
    margin-top: 30px;
    max-height: 300px;
    background-color: #333;
    padding: 0 15px;
}