jfroelich / rss-reader

A simple Chrome extension for viewing RSS feeds
Other
10 stars 0 forks source link

Create a test that articulates the behavior of time-deferred raised exceptions in context of a non-async promise executor #805

Closed jfroelich closed 5 years ago

jfroelich commented 5 years ago

Just to clarify, look at code like patch-entry. notice in the request success handler, it does not throw intentionally, it tries to reject. why? because if it throws, the outer promise never rejects. that is the whole problem. which means i do not understand something here. because this delayed exception is not being translated into a rejection.

jfroelich commented 5 years ago

https://stackoverflow.com/questions/41431605

jfroelich commented 5 years ago

The terminology and examples here are all confusing because the issue is very subtle. For example, it is very clear how this works:

new Promise(function executor(resolve, reject) {
  throw new Error('hi');
});

In the above example, the exception is clearly translated into a rejection. But that is because the error is thrown in the same tick as the executor function execution. The above example is not the issue.

The issue is in this example:

new Promise(function executor(resolve, reject) {
  setTimeout(function run_after_delay() {
    throw new Error();
  });
});

This kind of exception is not translated into a rejection. And unfortunately this is the kind of exception sometimes encountered when working with indexedDB.

jfroelich commented 5 years ago

Typical idb code that exhibits the unwanted behavior:

const promise = new Promise((resolve, reject) => {
  // this comment exists in timeline1
  conn.transaction('').objectStore('').openCursor().onsuccess = event => {
    // this comment exists in timeline 2
    if(edge_case) {
     throw error;
    }
  };
});

The error is thrown in the success event handler function. This function is happening in an alternate second timeline. The exception here breaks in the second timeline, but, it does nothing to reject the promise happening in the first timeline where the executor function wraps the cursor open call.

The issue is not the first comment, the issue is the second comment. In the scope of the first comment, exceptions are happening in the same tick as the promise executor function call, and are automatically translated into rejections. In the scope of the second comment, exceptions are not translated, and the promise never actually settles.

jfroelich commented 5 years ago

http://www.informit.com/articles/article.aspx?p=2102373&seqNum=3