-2

[Edit: this is a question about Promises, not setTimeout. Please don't close it without actually reading the question]

I'm trying to understand Promises. From what I've read and understood (which is obviously incomplete or wrong), the following should wait 3 seconds, append "in foo", then append "in bar".

However, "in bar" is first, followed by a 3 second wait, followed by "in foo".

I could use a shove in the right direction on this.

function promiseTest() {
  let promise = new Promise(function(resolve, reject) {
    setTimeout(foo, 3000);
  });
  promise.then(foo).then(bar());
}

function foo() {
  jQuery('#demo').append("<li>in foo</li>");
}

function bar() {
  jQuery('#demo').append("<li>in bar</li>");
}
<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <ul id='demo'></ul>
  <button onclick='promiseTest()'>click</button>
</body>

</html>
Bob Stout
  • 1,237
  • 1
  • 13
  • 26
  • https://stackoverflow.com/questions/42529476/let-promise-wait-a-couple-of-seconds-before-return does this help? – WOUNDEDStevenJones Mar 24 '22 at 19:06
  • I think I'd have to agree with the OP, without some explanation I don't see how this duplicate applies.. – Brian Thompson Mar 24 '22 at 19:06
  • Actually no, the duplicate does apply, it's just misleading because `setTimeout` is in the dupe title and that's not the problem code here. You're calling `bar()` in the `.then`, not passing it as a callback. – Brian Thompson Mar 24 '22 at 19:08
  • `promise.then(foo).then(bar);` – Brian Thompson Mar 24 '22 at 19:08
  • Your promise also never resolves, so none of this code `.then(foo).then(bar);` is actually ran. – Brian Thompson Mar 24 '22 at 19:12
  • 1
    Voted to reopen. The linked question doesn't seem directly relevant here. The answer here is related to resolving the promise, not the way they're calling `setTimeout`. I know there are a few issues here with `setTimeout(foo, 3000)` and `.then(foo)` and `.then(bar())`, but these multiple issues can be addressed in an answer, not a seemingly not-quite-related question. – WOUNDEDStevenJones Mar 24 '22 at 19:23
  • 1
    Does this answer your question? [In JavaScript, does it make a difference if I call a function with parentheses?](https://stackoverflow.com/questions/3246928/in-javascript-does-it-make-a-difference-if-i-call-a-function-with-parentheses) – jabaa Mar 24 '22 at 19:57

2 Answers2

2

Since this was reopened, and there multiple issues outside of the initial source of confusion, let me try to explain the problems.

1. Syntax for passing a callback

Executing a callback function is the responsibility of the function you pass it to. So in the case of setTimeout, you expect that after 3 seconds it will call the function you pass it.

const foo = () => console.log('foo');
setTimeout(foo, 3000);
// OR
setTimeout(() => console.log('foo'), 3000);

In both scenarios, you are passing a function, but never calling it yourself.

promise.then(foo).then(bar()) is a problem because you are calling bar, not passing it.

2. Unresolved promises

promise never completes, because you never called resolve or reject. This means, neither .then actually executes.

You were deceived into thinking they were because of the bug with bar().

Final solution

In order to accomplish what you want, you need to resolve the promise. But you need to do so after foo is called. The best way to do this may be to create an anonymous function for the setTimeout callback that calls both foo and resolve.

See below:

function promiseTest() {
  let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
      foo();
      resolve();
    }, 3000);
  });
  promise.then(bar);
}

function foo() {
  jQuery('#demo').append("<li>in foo</li>");
}

function bar() {
  jQuery('#demo').append("<li>in bar</li>");
}
<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <ul id='demo'></ul>
  <button onclick='promiseTest()'>click</button>
</body>

</html>
Brian Thompson
  • 13,263
  • 4
  • 23
  • 43
  • 1
    That's exactly what I was looking for. I didn't understand "resolve()", and was confused between "bar" and "bar()". MUCH thanks. – Bob Stout Mar 24 '22 at 20:25
0

The argument you're supposed to pass to then() needs to be a function, you are not passing the function bar, you are passing the result of calling the function bar.

Remove the parenthesis to refer to the function instead of the result of calling it.

Evert
  • 93,428
  • 18
  • 118
  • 189