I am working with the ArcGIS javascript api, which is built on require
and the asynchronous module defintion. To create a map, you define all your action inside the callback of the AMD require
statement:
require([
"esri/Map",
"esri/views/MapView"
], function(Map, MapView){
const map = new Map({ ... })
const view = new MapView({ ... })
})
I would like to be able to initialize this behavior on command from another module, as well as get access to the map
and view
objects that are defined within the AMD callback. In order to be able to initialize this on command, I can wrap it in a function, and export that function:
export const makeMap = () => {
require([esri modules], function(Map, MapView){
map = new Map({ ... })
view = new MapView({ ... })
})
}
I can import makeMap
into some other module in my code, and call it. This is working nicely. However, I am trying to figure out how I can then access the map
and view
objects to be able to manipulate them through the UI. First I tried this:
// mapMap.js
export const makeMap = () => {
let mapInstance;
let viewInstance;
require([esri modules], function(Map, MapView){
map = new Map({ ... })
view = new MapView({ ... })
mapInstance = map
viewInstance = view
})
return { mapInstance, viewInstance }
}
// some other module
import { makeMap } from './makeMap'
const { mapInstance, viewInstance } = makeMap()
This obviously does not work - mapInstance
and viewInstance
are undefined, as the function that defines them inside the AMD callback runs after they are returned from the makeMap()
call.
I am not sure how I can get a returned value from the AMD callback. Is this possible? Do I need another paradigm?
One other thing I tried is to pass in a reference-holder object, apply the reference to that object, and then just retrieve them from there when needed. It works, but I feel its not as clean:
// maprefs.js
export const maprefs = {}
// makeMap.js
import { maprefs } from './maprefs'
export const makeMap = (maprefs, mapname) => {
require([esri modules], function(Map, MapView){
map = new Map({ ... })
view = new MapView({ ... })
maprefs[mapname] = { map, view }
})
}
// some module
import { maprefs } from './maprefs'
import { makeMap } from './makeMap'
makeMap(maprefs, "map1")
someButton.addEventListener('click', () => {
// maprefs.map1 is properly defined as { mapInstance, viewInstance } and I can take action on it
maprefs.map1.doSomething
})
I took a look at How do I return the response from an asynchronous call?, which is about retuning values from ajax calls, but I'm struggling to relate that to AMD callbacks.
Is it possible to return the value from the AMD callback to be used elsewhere? I am hoping for a const { map, value } = makeMap()
type syntax.
In the scenario that you mention, I think that the best solution is to use esri-loader
. Is a tiny library built by ESRI for this purpose exactly, that is, load the ArcGIS JS API library modules at runtime.