Reputation: 1988
I'm having trouble understanding function scope when called in setInterval.
When I declare an anonymous function directly inside the setInterval like this:
let lastEventUUID = "some ID";
const interval = setInterval(async function() {
console.log("lastEventUUID -> " + lastEventUUID);
lastEventUUID = "another ID";
}, 1000);
Everything work as expected, I get
lastEventUUID -> some ID
lastEventUUID -> another ID
...
But when I declare my function separatly
async function myFunc(lastEventUUID) {
console.log("lastEventUUID -> " + lastEventUUID);
lastEventUUID = "another ID";
}
And call set it in the setInterval
:
let lastEventUUID = "some ID";
const interval = setInterval(myFunc, 1000, lastEventUUID);
The lastEventUUID
is not updated in the next call, I get
lastEventUUID -> some ID
lastEventUUID -> some ID
...
What am I missing here ?
Upvotes: 1
Views: 941
Reputation: 94
you can also achieve the same using Closures like this:
function myFunc(uuid) {
return function(){
console.log("lastEventUUID -> " + uuid);
uuid = "another ID";
}
}
let lastEventUUID = "some ID";
const interval = setInterval(myFunc(lastEventUUID), 1000);
Upvotes: 1
Reputation: 1074198
It's nothing to do with defining the function separately or not. In your first example, you're using the lastEventID
variable that the function closes over. In your second example, you're using the lastEventID
parameter that is passed to the function. Since setInterval
passes it the same one every time, you see the same one every time.
If you do like-for-like, you can define it separately:
async function myFunc() {
// ^----- No parameter declared
console.log("lastEventUUID -> " + lastEventUUID);
lastEventUUID = "another ID";
}
let lastEventUUID = "some ID";
const interval = setInterval(myFunc, 1000);
// No argument given to pass to myFunc --^
Side note: You've defined your function as an async
function. If your real function is using await
in the function body, be sure that you have a try
/catch
around the full body of the function and that you handle any errors; otherwise, an error will result in an "Unhandled rejection" error (since the timer mechanism isn't going to do anything with the promise your function returns, including handling rejections). If your real function doesn't use await
, there's no reason for it to be async
.
Re your comment:
From what I understand this work because here lastEventUUID is declared in the global scope, but in my case, it is defined in another function...
No, it doesn't work because it's a global. It works because it's declared in the scope the function is defined in or a parent scope. It works just fine if that's the scope of a function. Example:
function foo() {
async function myFunc() {
console.log("lastEventUUID -> " + lastEventUUID);
lastEventUUID = "another ID";
}
let lastEventUUID = "some ID";
const interval = setInterval(myFunc, 1000);
}
foo();
Globals are just an extreme case of this concept, which is called a closure. More: How do JavaScript closures work?
In fact, if we call that function twice, we see that there is a lastEventID
variable for each of them (which is entirely private to the stuff defined within foo
):
function foo(x) {
async function myFunc() {
console.log("x -> " + x + ", lastEventUUID -> " + lastEventUUID);
lastEventUUID = "another ID";
}
let lastEventUUID = "some ID";
const interval = setInterval(myFunc, 1000);
}
foo(1);
foo(2);
Upvotes: 5