77 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
let loadQueue = []
 | 
						|
let requestPool = []
 | 
						|
let pendingRequests = new Map()
 | 
						|
let requestCount = 0
 | 
						|
const batchSize = 8
 | 
						|
const debug = false
 | 
						|
 | 
						|
function recycledXMLHttpRequest() {
 | 
						|
    // https://nullprogram.com/blog/2013/02/08/
 | 
						|
    if (requestPool.length > 0) {
 | 
						|
        return requestPool.pop()
 | 
						|
    }
 | 
						|
    requestCount += 1
 | 
						|
    if (debug) console.log('create XMLHttpRequest', requestCount)
 | 
						|
    let xhr = new XMLHttpRequest()
 | 
						|
    return xhr
 | 
						|
}
 | 
						|
 | 
						|
function load() {
 | 
						|
    while (loadQueue.length > 0 && pendingRequests.size < batchSize) {
 | 
						|
        let tile = loadQueue.shift()
 | 
						|
        let [col, row, url] = tile
 | 
						|
        let xhr = recycledXMLHttpRequest()
 | 
						|
        xhr.onload = event => {
 | 
						|
            let buffer = xhr.response
 | 
						|
            postMessage({ success: true, url, col, row, buffer }, [buffer])
 | 
						|
            pendingRequests.delete(url)
 | 
						|
        }
 | 
						|
        xhr.onerror = event => {
 | 
						|
            let buffer = null
 | 
						|
            postMessage({ success: false, url, col, row, buffer })
 | 
						|
            pendingRequests.delete(url)
 | 
						|
        }
 | 
						|
        xhr.onreadystatechange = () => {
 | 
						|
            // In local files, status is 0 upon success in Mozilla Firefox
 | 
						|
            if (xhr.readyState === XMLHttpRequest.DONE) {
 | 
						|
                pendingRequests.delete(url)
 | 
						|
                requestPool.push(xhr)
 | 
						|
                if (debug) console.log('resuse XMLHttpRequest')
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (debug) console.log('open XMLHttpRequest')
 | 
						|
        xhr.open('GET', url, true)
 | 
						|
        xhr.responseType = 'arraybuffer'
 | 
						|
        if (debug) console.log('send XMLHttpRequest')
 | 
						|
        xhr.send()
 | 
						|
        pendingRequests.set(url, xhr)
 | 
						|
    }
 | 
						|
    if (loadQueue.length > 0) setTimeout(load, 1000 / 120)
 | 
						|
    else {
 | 
						|
        if (debug) console.log('tileloader ready')
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
self.onmessage = event => {
 | 
						|
    let msg = event.data
 | 
						|
    switch (msg.command) {
 | 
						|
        case 'load':
 | 
						|
            for (let tile of msg.tiles) {
 | 
						|
                loadQueue.push(tile)
 | 
						|
            }
 | 
						|
            load()
 | 
						|
            break
 | 
						|
        case 'abort':
 | 
						|
            loadQueue = []
 | 
						|
            requestPool = []
 | 
						|
            for (let xhr of pendingRequests.values()) {
 | 
						|
                xhr.abort()
 | 
						|
            }
 | 
						|
            pendingRequests.clear()
 | 
						|
            if (debug) console.log('tileloader aborted')
 | 
						|
            break
 | 
						|
        default:
 | 
						|
            console.warn('Unknown worker command: ' + msg.command)
 | 
						|
    }
 | 
						|
}
 |