1 | import methods from './methodsConfig'
|
2 | import { Map, MapboxEvent } from 'mapbox-gl'
|
3 |
|
4 | type Event = { eventId: string } & MapboxEvent
|
5 |
|
6 | function generateEventId(methodName: string): string {
|
7 | return `${methodName}-${('' + Math.random()).split('.')[1]}`
|
8 | }
|
9 |
|
10 | function catchEventFabric(
|
11 | map: Map,
|
12 | eventName: string,
|
13 | eventId: string,
|
14 | resolve: (event) => void
|
15 | ): (event: any) => void {
|
16 | const catchEvent = (event: Event) => {
|
17 | if (event.type !== eventName || event.eventId !== eventId) {
|
18 | return
|
19 | }
|
20 | map.off(eventName, catchEvent)
|
21 | resolve(event)
|
22 | }
|
23 | return catchEvent
|
24 | }
|
25 |
|
26 | function promisifyMethod(map: Map, methodName: string): (...args: any) => Promise<object> {
|
27 | const method = map[methodName]
|
28 | const argsCount = method.length
|
29 |
|
30 | return (...args) => {
|
31 | const handlers = []
|
32 | const eventData = { eventId: generateEventId(methodName) }
|
33 |
|
34 | const catchers = methods[methodName].events.map((event, index) => {
|
35 | return {
|
36 | event,
|
37 | func: new Promise((resolve, reject) => {
|
38 | handlers[index] = { event, func: catchEventFabric(map, event.name, eventData.eventId, resolve) }
|
39 | map.on(event.name, handlers[index].func)
|
40 | })
|
41 | }
|
42 | })
|
43 |
|
44 | const argsArray = []
|
45 |
|
46 | for (let i = 0; i < argsCount; i++) {
|
47 | if (i === argsCount - 1) {
|
48 |
|
49 |
|
50 | argsArray.push({ ...eventData, ...(args[i] || {}) })
|
51 | } else {
|
52 |
|
53 | argsArray.push(args[i] || null)
|
54 | }
|
55 | }
|
56 |
|
57 | let funcs = []
|
58 | let options = args[0] || {}
|
59 | try {
|
60 | method.apply(map, argsArray)
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 | if (methodName === 'fitBounds') {
|
67 |
|
68 | options = {}
|
69 | }
|
70 |
|
71 | if (methodName === 'fitScreenCoordinates') {
|
72 | options = { bearing: null }
|
73 | options.bearing = null
|
74 |
|
75 | if (typeof args[2] === 'number') {
|
76 | options.bearing = args[2]
|
77 | }
|
78 |
|
79 | if (args[3] && typeof args[3] === 'object') {
|
80 | options = {
|
81 | ...options,
|
82 | ...args[3]
|
83 | }
|
84 | }
|
85 | }
|
86 |
|
87 | funcs = catchers.map(({ event, func }) => {
|
88 | if (event.check(map, options)) {
|
89 | return func
|
90 | } else {
|
91 | map.off(event.name, func)
|
92 | return Promise.resolve()
|
93 | }
|
94 | })
|
95 | } catch (err) {
|
96 | handlers.forEach(({ event, func }) => {
|
97 | map.off(event.name, func)
|
98 | })
|
99 | throw err
|
100 | }
|
101 |
|
102 | return Promise.all(funcs).then(() => {
|
103 | return methods[methodName].getter(map)
|
104 | })
|
105 | }
|
106 | }
|
107 |
|
108 | export default promisifyMethod
|