0

promise with no setTimeout()

console.log('Prmoise start');
const lotteryPromise = new Promise(function (resolve, reject) {
   if(Math.random() >= 0.5) {
      resolve('You won the lottery');
   } else {
      reject(new Error('You lost your money'));
   }
});
 
lotteryPromise.then(res => console.log(res)).catch(err => console.error(err));
console.log('Promise end');

promise with setTimeout()

    console.log('Prmoise start');
    const lotteryPromise = new Promise(function (resolve, reject) {
    setTimeout( () => {
       if(Math.random() >= 0.5) {
          resolve('You won the lottery');
       } else {
          reject(new Error('You lost your money'));
       }
       },2000);
    });
     
    lotteryPromise.then(res => console.log(res)).catch(err => console.error(err));
    console.log('Promise end');

I don't understand the usage of setTimeout() wrap in promise? Even without the setTimeout() wapping the promise is gettitng executing asynchronously right i.e it is added to eventQueue ? Is that SetTimeout is just delaying the code execution or Is there anything else I am missing? By the way I know how call stack, micro tasks and callback queue works....

  • 1
    the difference is about 2 seconds in your code - note, the `Promise.end` is meaningless, as the Promise hasn't resolved yet when you console.log that, in either case – Jaromanda X May 17 '23 at 10:23
  • settimeout is just delaying the code, as you assumed. – ruud May 17 '23 at 10:27
  • let's wait for @T.J.Crowder to answer. I have an understanding of this behavior, but don't feel authoritative enough to answer the question – d.k May 17 '23 at 10:34
  • `Even without the timer wrap the promise is asynchronously executing right ?`, No.. They are just queued to run before the next macrotask. In fact if the browser doesn't get chance to execute another macrotask, it will even hang the browser like sync code would. – Keith May 17 '23 at 10:37
  • @Keith , Insn't that a code passed into queue is asynchronous ? Also answer me are promises in js asynchronous by default ? – Kondaveti Charan May 17 '23 at 16:03
  • @KondavetiCharan Not sure how I can explain things more than in my answer. Was there any part of that, that didn't make any sense?. Did you understand the reason why commenting out `await sleep(1)` caused the browser to hang/crash. – Keith May 17 '23 at 16:19

4 Answers4

3

You're addressing this problem backwards. You should be asking: What is the point of using a promise without setTimeout?

The purpose of a promise is to manage asynchronous code in a standard way.

The purpose of the new Promise constructor is to create a promise for asynchronous code which doesn't use promises natively.


In your first chunk of code, there is nothing asynchronous about the function you pass to Promise(). It's a pointless promise.

In your second chunk of code, the setTimeout is asynchronous but you've no way to know when it is finished (other than modifying the callback you pass to it). Using new Promise with it allows you to use the promise object to do something when the setTimeout is complete.

That said, there's no obvious reason to use setTimeout or promises at all for this example. It's entirely contrived to demonstrate how promises work, not to be a practical example of when you should use a promise or a timeout.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I wouldn't say that the first example is pointless. It is asynchronous, since Promises by definition run in another queue, but it's different from the other queue, which is used by setTimeout and some other tools, as @DevGajjar mentioned. Although it's similar to setTimeout(func, 0), it's still not a setTimeout call, and will be run earlier – d.k May 17 '23 at 10:40
  • 3
    @DmitryKoroliov No. Promises don't get added to an asynchronous queue, this is maybe the bit your getting confused. If they did that, performance would be a massive issue. What happens promises get queued, and when the next EVENT loop happens, these promises get executed. Try creating an infinite loop with promises, without allowing the browser to process an async event, like a timer, and you will see the browser will actually hang. – Keith May 17 '23 at 10:46
  • @Keith could you then explain quickly what does the term asynchronous mean? Since I always assumed it as anything added to any of the 2 queues, i.e. not executed immediately. What I mean, is that the callback to the Promise call in example 1 is not executed immediately, so there may be a point to use a Promise this way, as there may be a point to call setTimeout(f, 0) – d.k May 17 '23 at 10:51
  • @Keith sorry, but I didn't understand your point with an infinite loop, namely how it's different from the setTimeout case? If I have an infinite loop and call setTimeout in it, then, I'm sure, none of the callbacks will be executed either. So does it make the setTimeout also not asynchronous? I'm confused, honestly – d.k May 17 '23 at 10:53
  • 1
    @DmitryKoroliov Not sure the best way to explain, I'll maybe knock up a simple snippet, that show creating an infinate loop using promises, one that work, and one that doesn't. And then maybe explain the difference. – Keith May 17 '23 at 11:00
2

A slight miss conception of promises, is that there async. But there really only just a contract, that is then placed into a queue that will get processed before the next event loop. Very useful for writing async code, much nicer than callbacks.

Below is a simple example with 2 promises, 1 promise is not doing anything async, the other is doing a simple async sleep. That async sleep is very important, because this allows the browser to process the next event loop. If you take this sleep out, and re-run, watch how the browser will hang.

Please NOTE: be prepared to use say Chrome's task manager to kill the browser TAB when you comment out the await sleep(1).

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

async function nothingProm() {
  // a promise that does no async stuff
}

//this infinate loop will not hang the browser
async function test() {
  while (true) {
    await nothingProm();
    await sleep(1);  //remove this for HANG!!!     
  }
}

test();

Now in the above it might seem strange why does removing that sleep cause the browser to hang.

Browsers use something called an event loop, this is responsible for getting things like mouse clicks, timers etc, and dispatching them to listeners. This is very similar to how cooperative multi-tasking OS's work, think Window 3.11.

So, inside the browser TAB there will be an Event Loop running, doing something like ->

while (running) {
  var message = getNextMessage();
  dispatchMessage(message);
}

That getNextMessage above will efficiently wait for some event, timer, mouse move, etc etc. So it won't be wasting CPU resources, even thought it's in this tight LOOP.

So what does this have to do with promises you may ask. Well this bit is where the microtask comes in, unlike macrotask like a timer, that the browser can dispatch from, there basically stuck into a queue that get drained before the next macrotask is processed.

while (running) {
  var message = getNextMessage();  // (1)
  dispatchMessage(message);  // (2)
  processMicroTaskQueue(); // (3)
}

So if you had promises that's only did stage (3), constantly the browser gets stuck at (3), as such does not get any chance to process any macrotasks, IOW: The browser HANGS!!

Hopefully that makes sense, and I've used the correct terminology etc.

ps. Very similar to 3.11, a badly written app that never gave chance for the OS to process it's event loop, would in fact hang the whole OS. Strange how these things come round again.. :)

Keith
  • 22,005
  • 2
  • 27
  • 44
0

By adding a timer to your code, you are further confirming that the code inside the promise is running asynchronously. This is just to mimic the behavior of real-life examples for asynchronous operations like fetching data. It waits for 2 seconds then perform your operations and resolve afterwards.

Syed Ahmed
  • 112
  • 1
  • 7
-2

Promise.resolve schedules a microtask and the setTimeout schedules a macrotask. And the microtasks are executed before running the next macrotask.

Dev Gajjar
  • 21
  • 3