Google 个地图的 Web Worker 线程
Web Worker threads for Google Maps
我正在尝试使用网络工作线程在多对位置之间并行获取方向,最后将文本存储在一个文件中。顺序方法中的一切都进行得很顺利。我正在使用 npm live-server 来显示页面。但是浏览器在加载后立即关闭页面,我什至看不到呈现的内容或咨询控制台是否有错误。如果我在 index.html 中使用 'async defer' 作为我的脚本标记和 google Api,我将得到 "UncaughtReferenceError: google is not defined" 错误。提前谢谢大家!
这是我的 index.html:
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
#map {
height: 100%;
width: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
panel {
display: block;
}
</style>
</head>
<body>
<panel></panel>
<div id="map"></div>
<script src=locations.js></script>
<script src='main.js'></script>
<script src='worker.js'></script>
<script src="https://maps.googleapis.com/maps/api/js?key=<API-KEY>&callback=initMap"></script>
</body>
</html>
这是我的 main.js:
let worker = new Worker('worker.js');
worker.onmessage = function(info) {
output += info.data;
};
const container = document.querySelector('panel');
let output = ""
function initMap() {
locations.forEach( spot => {
worker.postMessage(spot);
});
download("data.txt", output, 'text/plain');
console.log("Output: " + output);
}
function download(name, text, type) {
const file = new Blob([text], {type: type});
const atag = '<a href="' + URL.createObjectURL(file) + '" download="' + name + '">Download</a>';
container.insertAdjacentHTML('afterbegin', atag);
}
最后 worker.js:
let directionsService;
let directionsDisplay;
let map;
self.addEventListener('message', (e) => {
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
const mapOptions = {
center: {lat: 30, lng: -90},
zoom: 6
}
map = new google.maps.Map(document.getElementById('map'), mapOptions);
directionsDisplay.setMap(map);
let request = {
origin: 'New Orleans, LA',
destination: e.data,
travelMode: 'DRIVING',
provideRouteAlternatives: false,
drivingOptions: {
departureTime: new Date('September 7, 2018 15:00:00'),
trafficModel: 'pessimistic'
},
unitSystem: google.maps.UnitSystem.IMPERIAL
};
directionsService.route(request, (result, status) => {
if (status == 'OVER_QUERY_LIMIT') {
console.log('over');
}
if (status == 'INVALID_REQUEST'){
console.log('other status')
}
if (status == 'OK') {
var data = result["routes"][0].legs[0];
postmessage(e.data + ", " + data["distance"].text + ", " + data["duration"].text + "\n");
directionsDisplay.setDirections(result);
console.log(result);
}
});
self.close();
});
网络工作者在 Javascript 中有自己的范围。这意味着您在网页范围内加载的任何脚本在 web worker 范围内都将不可用。
通常您使用 importScripts 调用来加载脚本。但是,这在您的情况下不起作用,因为您还尝试访问网络工作者中的 DOM 。由于多种原因,这在 Web Worker 中是不可能的(最重要的是并发访问非线程保存的数据结构)。
查看您的代码,我认为您不需要网络工作者来计算路由。无论如何,实际路由很可能是在其中一台 Google 服务器上完成的。由于无论如何这都是异步的,因此您无需担心会阻止网页的 UI。
我正在尝试使用网络工作线程在多对位置之间并行获取方向,最后将文本存储在一个文件中。顺序方法中的一切都进行得很顺利。我正在使用 npm live-server 来显示页面。但是浏览器在加载后立即关闭页面,我什至看不到呈现的内容或咨询控制台是否有错误。如果我在 index.html 中使用 'async defer' 作为我的脚本标记和 google Api,我将得到 "UncaughtReferenceError: google is not defined" 错误。提前谢谢大家!
这是我的 index.html:
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
#map {
height: 100%;
width: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
panel {
display: block;
}
</style>
</head>
<body>
<panel></panel>
<div id="map"></div>
<script src=locations.js></script>
<script src='main.js'></script>
<script src='worker.js'></script>
<script src="https://maps.googleapis.com/maps/api/js?key=<API-KEY>&callback=initMap"></script>
</body>
</html>
这是我的 main.js:
let worker = new Worker('worker.js');
worker.onmessage = function(info) {
output += info.data;
};
const container = document.querySelector('panel');
let output = ""
function initMap() {
locations.forEach( spot => {
worker.postMessage(spot);
});
download("data.txt", output, 'text/plain');
console.log("Output: " + output);
}
function download(name, text, type) {
const file = new Blob([text], {type: type});
const atag = '<a href="' + URL.createObjectURL(file) + '" download="' + name + '">Download</a>';
container.insertAdjacentHTML('afterbegin', atag);
}
最后 worker.js:
let directionsService;
let directionsDisplay;
let map;
self.addEventListener('message', (e) => {
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
const mapOptions = {
center: {lat: 30, lng: -90},
zoom: 6
}
map = new google.maps.Map(document.getElementById('map'), mapOptions);
directionsDisplay.setMap(map);
let request = {
origin: 'New Orleans, LA',
destination: e.data,
travelMode: 'DRIVING',
provideRouteAlternatives: false,
drivingOptions: {
departureTime: new Date('September 7, 2018 15:00:00'),
trafficModel: 'pessimistic'
},
unitSystem: google.maps.UnitSystem.IMPERIAL
};
directionsService.route(request, (result, status) => {
if (status == 'OVER_QUERY_LIMIT') {
console.log('over');
}
if (status == 'INVALID_REQUEST'){
console.log('other status')
}
if (status == 'OK') {
var data = result["routes"][0].legs[0];
postmessage(e.data + ", " + data["distance"].text + ", " + data["duration"].text + "\n");
directionsDisplay.setDirections(result);
console.log(result);
}
});
self.close();
});
网络工作者在 Javascript 中有自己的范围。这意味着您在网页范围内加载的任何脚本在 web worker 范围内都将不可用。
通常您使用 importScripts 调用来加载脚本。但是,这在您的情况下不起作用,因为您还尝试访问网络工作者中的 DOM 。由于多种原因,这在 Web Worker 中是不可能的(最重要的是并发访问非线程保存的数据结构)。
查看您的代码,我认为您不需要网络工作者来计算路由。无论如何,实际路由很可能是在其中一台 Google 服务器上完成的。由于无论如何这都是异步的,因此您无需担心会阻止网页的 UI。