​

In light of Async Functions in ES7, it may make sense to separate the 
abstractions between promises and cancellation. Promises and cancellation 
signals have different use cases:


Promises

  *   Promises are consumed by the caller and produced by the callee.
  *   Observation a promise resolution can only happen in a later turn.
  *   The consumer of a promise cannot directly resolve the promise.

Cancellation

  *   Cancellation signals are produced by the caller and consumed by the 
callee.
  *   Observation a cancellation signal must happen immediately.
  *   The consumer of a cancellation token cannot directly cancel the token.

API Proposal:


class CancellationTokenSource {
  /** Create a new CTS, optionally with an iterable of linked cancellation 
tokens. */
  constructor(linkedTokens?: Iterable<CancellationToken>);

  /** Gets the cancellation token for this source. */
  get token(): CancellationToken;

  /** Cancels the source and sends a cancellation signal with an optional 
reason (default Error("Operation canceled")). */
  cancel(reason?: any): void;

  /** Cancels the source after a delay (in milliseconds), with an optional 
reason. */
  cancelAfter(delay: number, reason?: any): void;

  /** Prevents any possible future cancellation of the source and removes all 
linked registrations. */
  close(): void;
}

class CancellationToken {
  /** Gets a cancellation token that can never be canceled. */
  static get default(): CancellationToken;
  /** Gets a value indicating whether the cancellation signal was sent. */
  get canceled(): boolean;
  /** If canceled, gets the reason for cancellation if provided; otherwise, 
returns `undefined`. */
  get reason(): any;
  /** If canceled, throws either the reason or a general “Operation Canceled” 
error. */
  throwIfCanceled(): void;
  /**
    * Registers a callback to execute immediately when a cancellation signal is 
received.
    * The callback can be removed using the `unregister` method of the return 
value.
    */
  register(callback: (reason: any) => void): { unregister(): void };
}


Usage (Abort):


```
// aborts and throws error when canceled
function fetchAsync(url, cancellationToken = CancellationToken.default) {
  return new Promise((resolve, reject) => {
    cancellationToken.throwIfCanceled();
    var xhr = new XMLHttpRequest();
    var registration = cancellationToken.register(() => xhr.abort());
    xhr.open("GET", url, /*async*/ true);
    xhr.onload = event => {
        registration.unregister();
        resolve(xhr.responseText);
    };
    xhr.onerror = event => {
        registration.unregister();
        reject(xhr.statusText);
    }
    xhr.send(null);
  });
}

fetchAsync(...).then(...); // as expected

var cts1 = new CancellationTokenSource();
fetchAsync(..., cts1.token).catch(...);
cts1.cancel(new Error("Operation Canceled"); // .catch gets the error and the 
xhr is aborted.


Usage (Ignore):


// ignore operation/stop processing
async function startTicker(receiveSymbol, cancellationToken = 
CancellationToken.default) {
    while (!cancellationToken.canceled) {
        var symbols = await fetchSymbols();
        for (var symbol of symbols) {
            receiveSymbol(symbol);
        }
    }
}

var stopTicker = new CancellationTokenSource();
stopTicker.cancelAfter(5 * 60 * 1000); // stop after 5 minutes.
startTicker(..., stopTicker.token).catch(...); // .catch only gets error from 
`fetchSymbols`.


Ron

________________________________
From: es-discuss <es-discuss-boun...@mozilla.org> on behalf of Dean Tribble 
<trib...@e-dean.com>
Sent: Monday, March 02, 2015 1:25 PM
To: Kevin Smith
Cc: public-script-co...@w3.org; es-discuss
Subject: Re: Cancellation architectural observations

On Mon, Mar 2, 2015 at 6:32 AM, Gray Zhang 
<otakus...@icloud.com<mailto:otakus...@icloud.com>> wrote:

+1 to the ignore term, I’ve opened an issue about it in 
https://github.com/promises-aplus/cancellation-spec/issues/14

I have little attachment to any term, but there's value in keeping terminology 
that has years of investment and use in other contexts. However "ignore" also 
has the wrong sense, because it implies that the computation completes anyway. 
That can be accomplished more easily by simply dropping the promise.

IMO the term cancel(or abort) and ignore are totally different things, the 
former one means “do not continue, stop it right now” and the “stop” state 
should be broadcast to everyone who is interested in the work, while the latter 
means “I don’t care about the result anymore, just play it as you like”, it 
means the async progress can be continued

 This goes back to some of the observations above: you cannot stop it "right 
now" because async notification is not synchronous; indeed the operation may 
already be complete before you stop it. Thus consumers of the result of a 
cancellable request need to be able to handle either successful completion or 
the cancelled state (which just looks like any other error that prevented 
completion).  Attempting broadcast to "everyone" adds complexity and resources 
that are needed only in the rare cancellation case. It's typically not only not 
worth the software complexity, but not a good idea. When you cancel a print 
job, the document editor should make best efforts in the background to stop 
requesting fonts, stop laying out print pages, stop spitting out pages on the 
printer, etc. but most importantly, it should start paying attention to my new 
edits and hang waiting for everything that might be involved in printing to 
wrap itself up.

In practice both scenario are commonly seen, we may abort a resource fetch in 
order to save bandwidth and opened connections, or we may in other side just 
ignore it since continue to complete the fetch can result in a local cache, 
which speeds up our fetch next time

The resource point is important. That's the "don't care" scenario, not the 
"abort" scenario. It's the request processor that knows what cleanup is worth 
the effort. The initiator of the request only knows they don't care about the 
result anymore.
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to