On MDN article about eval
there's a paragraph titled Use functions instead of evaluating snippets of code, in the example code there's a reference about setTimeout(). I can't grasp why this advice/command, so, keeping the setTimeout() reference, could someone point me out why these codes work as expected:
function timedPromise(){
return new Promise((resolve) => {
setTimeout(( ) => {resolve(console.log('Promise resolved!'))}, 1000)
})
};
function timedPromise2(){
return new Promise((resolve) => {
setTimeout(function(){resolve(console.log('Another promise resolved!'))}, 2000)
})
};
timedPromise();
timedPromise2();
/*output:
Promise {<pending>}
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
Promise resolved! //after at least 1s
Another promise resolved! //after at least 2s
*/
While this code won't?
function timedPromise(){
return new Promise((resolve) => {
setTimeout(resolve(console.log('I resolved!')), 1000)
})
};
timedPromise();
/*output:
I resolved! //immediate
Promise {<fulfilled>: undefined}
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
*/
I understand the browser evaluates the code snippet as a string
instead of a function, and then interprets it and executes it immediately instead of waiting for the delay of setTimeout() to pass.
Why though?
Why/when should I use wrapper functions instead of code snippets as parameters? Is it a thing related only to asynchronicity?
When you write functionName()
, the ()
call the function immediantly.
So when you write setTimeout(resolve(console.log('I resolved!')), 1000)
it:
console.log
first to pass its return value into resolve
;resolve
to pass it's value into setTimeout
;setTimeout
.When you wrap a function in a lambda, you're passing a reference to that function through, rather than calling it immediantly. It might be clearer to see like this:
function doLog() { console.log("Hello, world!"); }
// Calls doLog instantly, passes in return value of undefined
setTimeout(doLog(), 1000);
// Passes in a reference to doLog, which setTimeout will then call later
setTimeout(doLog, 1000);