Skip to content

Commit

Permalink
Chore: Refactor rejection tracking and add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
nzakas committed Jan 7, 2021
1 parent 98ae59d commit d12c1d4
Showing 1 changed file with 49 additions and 16 deletions.
65 changes: 49 additions & 16 deletions src/rejection-tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ import { PledgeSymbol } from "./pledge-symbol";
// https://html.spec.whatwg.org/multipage/webappapis.html#promiserejectionevent
//-----------------------------------------------------------------------------

const canceled = Symbol("canceled");

class PledgeRejectionEvent {
constructor(pledge, reason) {
this.pledge = pledge;
this.reason = reason;
this[canceled] = false;
this.returnValue = true;
}

preventDefault() {
this[canceled] = true;
this.returnValue = false;
}
}

Expand All @@ -28,23 +26,37 @@ export class RejectionTracker {
constructor(logger = console) {

/**
* This set keeps track of promises that were rejected but were not
* handled. All promises in this set will trigger an unhandledrejection
* event if they are still there during the monitoring phase of
* the rejection tracking.
* This set keeps track of pledges that were rejected but were not
* handled. All pledges in this set will trigger onUnhandledRejection
* if they are still there during the monitoring phase of the
* rejection tracking.
* @type Set
* @property aboutToBeNotified
*/
this.aboutToBeNotified = new Set();

/**
* This set keeps track of rejected promises that have been handled
* and will trigger a rejectionhandled event.
* @type Set
* This set keeps track of pledges that were unhandled, triggered
* onUnhandledRejection, and then had a rejection handler added. These
* pledges will trigger onRejectionHandled.
* @type WeakSet
* @property outstandingRejections
*/
this.outstandingRejections = new WeakSet();

/**
* A logger used to output unhandled pledge rejection notices. This
* can be overwritten for easier testing but otherwise is console.
* @type console
* @property logger
*/
this.logger = logger;

/**
* Tracks the interval identifier for monitoring pledges.
* @type int
* @property timeoutId
*/
this.timeoutId = 0;
}

Expand Down Expand Up @@ -74,16 +86,22 @@ export class RejectionTracker {
const event = new PledgeRejectionEvent(p, p[PledgeSymbol.result]);
p.constructor.onUnhandledRejection(event);

const notHandled = !event[canceled];

/*
* In the browser, "not handled" is a term that means both that
* the promise hasn't been handled and that the event handler
* did not cancel the event.
*/
const notHandled = event.returnValue;

/*
* The onUnhandledRejection handler might have added a rejection
* handler, so we need to double-check here.
*/
if (p[PledgeSymbol.isHandled] === false) {
this.outstandingRejections.add(p);
}

if (notHandled) {

// what to do here?

this.logger.error(`Pledge rejection was not caught: ${ p[PledgeSymbol.result] }`);
}
}
Expand All @@ -97,20 +115,35 @@ export class RejectionTracker {

track(pledge, operation) {

// the pledge has no rejection handler so we might need to log it
if (operation === "reject") {
this.aboutToBeNotified.add(pledge);
}

// the pledge was unhandled but now is handled
if (operation === "handle") {

/*
* If the pledge was going to trigger onUnhandledRejection, remove
* it from the list so that doesn't happen.
*/
if (this.aboutToBeNotified.has(pledge)) {
this.aboutToBeNotified.delete(pledge);
return;
}

/*
* If the pledge isn't already flagged to trigger
* onRejectionHandled, then there's nothing else we need to do.
*/
if (!this.outstandingRejections.has(pledge)) {
return;
}

/*
* If we made it here, the pledge was already flagged to trigger
* onRejectionHandled, so remove it and trigger the event.
*/
this.outstandingRejections.delete(pledge);

setTimeout(() => {
Expand Down

0 comments on commit d12c1d4

Please sign in to comment.