-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
114 lines (101 loc) · 2.58 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
'use strict';
const request = require('request');
const pify = require('pify');
const wait = require('wait-then');
const rand = require('random-int');
const API_GET_GEO =
'http://polygons.openstreetmap.fr/get_geojson.py?params=0&id=';
let last = null;
/**
* Returns the GeoJSON of a particular OSM relation id.
* @public
* @param {string} osmid Relation id from which extract the GeoJSON.
* @return {Promise<object>} A promise that contains the GeoJSON of the given
* relation.
*/
function getGeoJson(osmid) {
const opts = {
url: API_GET_GEO + osmid
};
if (last === null) {
last = Date.now();
}
// We don't want to flood the API.
let delta = 50 - (Date.now() - last) + rand(50);
if (delta < 0) {
delta = 0;
}
return new Promise((resolve, reject) => {
wait(delta)
.then(() => {
last = Date.now();
return pify(request)(opts);
})
.then(response => {
if (
!response ||
!response.body ||
response.body.substr(0, 4) === 'None' ||
response.statusCode === 500
) {
reject(
new Error('Unable to get response for the relation: ' + osmid)
);
return;
}
if (response.statusCode !== 200) {
getGeoJson(osmid)
.then(resolve)
.catch(reject);
return;
}
try {
const geojson = JSON.parse(response.body);
resolve(geojson);
} catch (err) {
getGeoJson(osmid)
.then(resolve)
.catch(reject);
}
})
.catch(() => {
getGeoJson(osmid)
.then(resolve)
.catch(reject);
});
});
}
/**
* Returns a map of GeoJSON of multiple OSM relation ids.
* @public
* @param {object} map Map from a name to a relation id from which extract the GeoJSON.
* @return {Promise<object>} A promise that contains the map with the same keys
* of the map provided but with the GeoJSON of the given relation id as value.
*/
function getAllGeoJson(map) {
const promises = [];
const geojsonMap = {};
for (const country of Object.keys(map)) {
promises.push(
new Promise((resolve, reject) => {
getGeoJson(map[country])
.then(geoJson => {
geojsonMap[country] = geoJson;
resolve();
})
.catch(reject);
})
);
}
return new Promise((resolve, reject) => {
Promise.all(promises)
.then(() => {
resolve(geojsonMap);
})
.catch(reject);
});
}
module.exports = {
get: getGeoJson,
getAll: getAllGeoJson
};