1

I want to be able to reject and stop the rest of the promise from running if an external event occurs. This is the example usecase:

new Promise((resolve,reject)=>{
    websocket.onerror=reject;
    //do processing here
    websocket.onerror=undefined;
    resolve(...);
});

This has the intended effect of rejecting the promise if an error occurs while the promise is running. However, the problem is that the rest of the promise will continue running even if a rejection occurs.

Using async/await the above is not possible at all.

I think one way would be to have every single line of code in a separate promise, and cancelling the chain on an event, but that would be a pain.

2 Answers2

0

However, the problem is that the rest of the promise will continue running even if a rejection occurs.

This is a basic misunderstanding (and you're not alone in it!). There is no "rest of the promise." A promise is just a means of observing the completion of an asynchronous process. It's the process, not the promise, that's continuing.

How you cancel that process (and whether you can) depends entirely on what that process is and whether it provides a means of cancelling it, which is unrelated to promises themselves. You seem to be using a web socket, so you'd need to use the web socket API to cancel whatever you have it doing (or to send a message to the other end to tell it to stop what it's doing).

For instance: Suppose the promise were waiting for a timer (setTimeout) to fire, and would resolve when it did. Then some other thing happens and you no longer want that. Rejecting the promise just rejects the promise, it doesn't have any effect on the timer. You'd need to cancel the timer, too (clearTimeout).


Re your edit:

I think one way would be to have every single line of code in a separate promise, and cancelling the chain on an event, but that would be a pain.

No, the code in the promise executor (the function you pass new Promise) is run synchronously. Again, there's no "rest of the code" to cancel. There may well be asynchronous callbacks in there, or a process the code starts you need to send a cancellation too, but that's not going to require putting every line in its own promise, not at all.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • So the event will never fire while the synchronous code is running? –  Aug 15 '18 at 14:13
  • @sunny-lan - The event may fire, but the callback for it will sit in the job queue until the current job (running the synchronous code in the promise executor) is complete. It's too late to add it to *this* question, but if you're unsure what to cancel or where in your real code, I suggest posting a new question with a [mcve] of that code, showing the actual things you're doing, so people can help you to know what, if anything, needs to be cancelled in it. – T.J. Crowder Aug 15 '18 at 14:15
0

Understanding the answer to this question may help you:

When you create the promise, it is executed synchronously. So this line is executed:

websocket.onerror=reject;

At this point, your code begins to process. If there is an event of websocket error, it is put in the js event loop, but your promise is still executing synchronously. Then you unhook the websocket's error handler, and resolve. The promise will resolve even if there was an error. At this point the call for resolve is also added to js' event loop. Then the next js tick executes, and maybe reject is called, maybe not, but it doesn't matter at this point because you resolved synchronously, and promises never change their minds once they've resolved or rejected.

So the key takeaway here is that creating a promise executes it synchronously. It's not a thread that you can cancel while waiting for other events. The promise' resolution or rejection is executed asynchronously, but that doesn't help you at all.

To cancel a promise, you'll need some pretty basic stuff such as

if(someOtherVariableThatDeterminesCancelation){
  reject()
}
Guillaume CR
  • 3,006
  • 1
  • 19
  • 31