I am developing a script that loads a series of elements, each function is returning an axios request to a different endpoint.
What I'm trying to do is verify that the first request "createTransportNetworkToMap" is executed first, and within this that the value of = "loading map" is added to the loadingItem variable.
Since the previous value was null, the watch is supposed to pick up the change and emit an event to another parent component, which will display the new value on the console.
After this, the request is made and it is waited for it to finish to show a console log. Now when it's done, it would be passed to the next function which does something similar but with different values.
This is the code:
export default {
name: "Map",
data: function() {
return {
map: null,
mapIsLoaded: false,
loadingItem: null
};
},
mounted: function() {
this.map = loadMap();
this.loadLayersToMap(this.map);
},
watch: {
loadingItem: function() {
EventBus.$emit("loadingItemChanged", this.loadingItem);
},
mapIsLoaded: function() {
EventBus.$emit("mapIsLoaded", this.mapIsLoaded);
}
},
methods: {
loadLayersToMap: function(map) {
Promise.all([
this.createTransportNetworkToMap(map),
this.createLinesToMap(map)
]);
this.mapIsLoaded = true;
},
createTransportNetworkToMap: function(map) {
return new Promise(() => {
this.loadingItem = "Cargando mapa";
}).then(
_createTransportNetworkToMap(map).then(() => {
console.log("mapa cargado");
})
);
},
createLinesToMap: function(map) {
return new Promise(() => {
this.loadingItem = "Cargando líneas";
}).then(
_createLinesToMap(map).then(() => {
console.log("Líneas cargadas");
})
);
},
getLoadingItem: function(item) {
this.loadingItem = item;
}
}
};
Unfortunately it doesn't run as I want and it shows me this:
It doesn't execute it in order and also it only shows me the last change.
The order in which promises are terminated does not depend on the order in which you execute them, but rather on the time they take. To avoid these problems there are several ways to do it:
Chaining promises:
Using callbacks:
async/await:
I don't quite understand what they do
_createTransportNetworkToMap
and_createLinesToMap
why I don't see their definition, but I imagine they are asynchronous functions that make the call by axios that you mentioned. For what calls us:when you do
First, you run the promises in parallel and there is no way to guarantee the order. Second, the call to
this.mapIsLoaded
executes immediately before the promises are resolved. If you want to execute them in sequence you could call them like:But considering that we are in 2019, you better just do
Another observation :
createTransportNetworkToMap
andcreateLinesToMap
they return a promise. But the promise constructor is not automatically resolved by doing a return. In your case the behavior of the message on screen and console is a secondary effect.It should be much simpler:
And the same, mutatis mutandi , with the other method.
loadLayersToMap
invokes the other comsawait
so it will treat the result as a promise. For its part, axios will return a promise to you. You don't need to wrap it by hand in a promise constructor.Since the await calls are in order, you can simplify further:
Note that I am handling loadingItem and the console.log in the methods and not in the main stream, simply to follow the single responsibility principle. The main callee just needs to know that it should call the methods in sequence. Those methods must worry about informing what they are dedicating themselves to.
Also notice that there is no catch on the child methods. The eventual exception will go upstream and you'll catch it in the main method. A single point of failure saves you several nightmares.
Just as a suggestion , you don't need to put watchers in the component's data. You can handle them as computed properties.
The component knows when to change its states, the watcher is less efficient and would only make sense if you watch a value that it doesn't control itself (like props)