let currentEndpoint = 'https://update.react-native.cn/api'; function ping(url, rejectImmediate) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.onreadystatechange = (e) => { if (xhr.readyState !== 4) { return; } if (xhr.status === 200) { resolve(url); } else { rejectImmediate ? reject() : setTimeout(reject, 5000); } }; xhr.open('HEAD', url); xhr.send(); xhr.timeout = 5000; xhr.ontimeout = reject; }); } function logger(...args) { // console.warn('pushy', ...args); } let backupEndpoints = []; let backupEndpointsQueryUrl = 'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json'; export async function tryBackupEndpoints() { if (!backupEndpoints.length && !backupEndpointsQueryUrl) { return; } try { await ping(getStatusUrl(), true); logger('current endpoint ok'); return; } catch (e) { logger('current endpoint failed'); } if (!backupEndpoints.length && backupEndpointsQueryUrl) { try { const resp = await fetch(backupEndpointsQueryUrl); backupEndpoints = await resp.json(); logger('get remote endpoints:', backupEndpoints); } catch (e) { logger('get remote endpoints failed'); return; } } await pickFatestAvailableEndpoint(); } async function pickFatestAvailableEndpoint(endpoints = backupEndpoints) { const fastestEndpoint = await Promise.race( endpoints.map(pingAndReturnEndpoint), ); if (typeof fastestEndpoint === 'string') { logger(`pick endpoint: ${fastestEndpoint}`); currentEndpoint = fastestEndpoint; } else { logger('all remote endpoints failed'); } } async function pingAndReturnEndpoint(endpoint = currentEndpoint) { return ping(getStatusUrl(endpoint)).then(() => endpoint); } function getStatusUrl(endpoint = currentEndpoint) { return `${endpoint}/status`; } export function getCheckUrl(APPKEY, endpoint = currentEndpoint) { return `${endpoint}/checkUpdate/${APPKEY}`; } export function getReportUrl(endpoint = currentEndpoint) { return `${endpoint}/report`; } export function setCustomEndpoints({ main, backups, backupQueryUrl }) { currentEndpoint = main; backupEndpointsQueryUrl = null; if (Array.isArray(backups) && backups.length > 0) { backupEndpoints = backups; pickFatestAvailableEndpoint(); } if (typeof backupQueryUrl === 'string') { backupEndpointsQueryUrl = backupQueryUrl; } }