It's a matter of timing. When you look at the variable outside the .then()
handler, you're looking at the value BEFORE the promise has resolved and before your value has been set. If you put several console.log()
statements at the various points in your code, you will see that you are attempting to examine and use the img
variable BEFORE the callback has run and set the value.
This uncertainty of timing (you never know precisely when a promise is going to be resolved) is why you almost never use the pattern you show where you assign a value to a higher scoped variable inside some asynchronous callback. Instead, you either use the value inside the callback or you call some function from within the callback and pass it the value as a function argument. Then, and only then, do you know the value is available and ready for use.
To illustrate the timing issue, try this code:
var img; //declaring the global variable
axios.get('https://i8xla88513.execute-api.us-east-1.amazonaws.com/latest/items')
.then(function (res){
for(i in res.data){ //This searches through the API
if(res.data[i].name === imgSearch){
console.log("about to set img");
img = res.data[i].image; //This assigns a value to the global function
break;
}
}
});
console.log("about to inspect img");
console.log(img);
When you run this, you will see the this sequence in the console:
about to inspect img
undefined
about to set img
This shows you how you were attempting to use the variable BEFORE the asynchronous callback had been called so the variable had not yet been set with its value. This is because axios.get()
is asynchronous and non-blocking. Calling it just initiates the http request and then the Javascript interpreter immediately executes the next lines of code after it (not inside the .then()
, but after that). Then, sometime later when the axios call finishes, the promise resolves and it calls the .then()
handler.
So, instead, do something like this:
axios.get('https://i8xla88513.execute-api.us-east-1.amazonaws.com/latest/items').then(function (res) {
for(let i in res.data){ //This searches through the API
if(res.data[i].name === imgSearch){
let img = res.data[i].image;
// call some function and pass the variable to that function
callMyFunction(img);
break;
}
}
});
Also, note that for(i in res.data)
is attempting to use an undeclared variable i
which makes it an implicit global which is a bad thing to do in for
loop. ALWAYS declare all variables before using them. In this case, this can be:
for (let i in res.data)
Of, if res.data
is an Array, then this really should be:
for(let obj of res.data) {
if (obj.name === imgSearch) {
let img = obj.image;
// call some function and pass the variable to that function
callMyFunction(img);
break;
}
}
As you shouldn't be using in
to iterate the elements of an array. That iterates the properties of an object which can include more items than just array elements. Use of
to iterate an array.