<html><head><style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}

h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}

h1 {
        color: #000000;
        font-size: 28pt;
}

h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}

h3 {
        font-size: 18px;
}

h4 {
        font-size: 16px;
}

h5 {
        font-size: 14px;
}

h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}

hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
    display: inherit;
}

p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}

a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}

#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}

button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}

code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}

code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}

pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}

pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}

#ws { background-color: #f8f8f8; }


.bloop_markdown table {
border-collapse: collapse;  
font-family: Helvetica, arial, freesans, clean, sans-serif;  
color: rgb(51, 51, 51);  
font-size: 15px; line-height: 25px;
padding: 0; }

.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
     
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }

.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }

.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }

.bloop_markdown blockquote{
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

code, pre, #ws, #message {
    word-break: normal;
    word-wrap: normal;
}

hr {
    display: inherit;
}

.bloop_markdown :first-child {
    -webkit-margin-before: 0;
}

code, pre, #ws, #message {
    font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}


.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="bloop_markdown"><p>+1 to the <code>ignore</code> term, I’ve opened an issue about it in https://github.com/promises-aplus/cancellation-spec/issues/14</p>

<p>IMO the term <code>cancel</code>(or <code>abort</code>) and <code>ignore</code> 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</p>

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

<p>Back to the <code>ignore</code> scenario, there is still some confusion left for me:</p>

<ol>
<li>Should <code>ignore</code> be a individual behavior, or a global one. This means should we just be able to “ignore” one callback, or just take a promise to a “ignore” state in which all callbacks are revoked</li>
<li>Should later <code>then</code> calls be aware that the promise is already <code>ignored</code>, or ignorance should be completely transparent to clients (which means all later <code>then</code> are effortless)</li>
</ol>

<p></p></div><div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;"><br></div> <br> <div id="bloop_sign_1425305910479810048" class="bloop_sign"><div class="bloop_markdown"><hr>

<p>Best regards</p><p>Gray Zhang</p>

<p></p></div><div class="bloop_original_html"><div style="font-family:helvetica,arial;font-size:13px"><br></div></div><div class="bloop_markdown"><p></p></div></div> <br><p style="color:#000;">在 2015年3月2日   下午7:26:52, Gundersen Marius (<a href="mailto:gundersen@gmail.com">gundersen@gmail.com</a>) 写到:</p> <blockquote type="cite" class="clean_bq"><span><div><div></div><div>


<title></title>


<div dir="ltr">
<div>
<div>I think a better term than cancel would be ignore. If the
promise has side effects then it is impossible for a cancel method
to guarantee that the side effects do not happen. For example a
POST request to the server that updates the server state can be
cancelled, but it is not possible to know if it happens before or
after the server has updated its state. It is therefore dangerous
to think of it as cancelling. A better concept is to ignore the
results of the promise. Even if the promise has been completed, the
results can be ignored. Depending on what job the promise is doing
it can decide if it wants to stop the task or not. A simple async
task might not need to have a way to be cancelled; the result of
the task can just be ignored. But a long running task that is
ignored might decide to stop what it is doing to save processing
power/battery.<br>
<br></div>
```js<br>
//this promise has a way to stop what it is doing<br>
var p1 = new Promise(function(resolve, reject, ignored){<br>
  var task = setTimeout(resolve.bind(null, "the result"),
1000);<br>
  ignored(() => clearTimeout(task));<br>
});<br>
<br></div>
//ignore the result from the above promise, triggers the ignored
listener<br>
<div>p1.ignore();<br></div>
<div>p1.then(result => "this is never called");<br></div>
<div><br>
//this promise cannot be cancelled, but the result can be
ignored<br>
var p2 = Promise.resolve("the result");<br>
<br>
//the callback is not called until next event loop cycle<br>
p2.then(result => "this is never called");<br>
<br>
//the result is ignored, the above callback is never run<br>
p2.ignore();<br>
```<br>
<br></div>
<div>Maybe calling ignore on a rejected or resolved promise should
throw.<br>
<br></div>
<div>Marius Gundersen<br></div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Mon, Mar 2, 2015 at 8:59 AM, Salvador
de la Puente González <span dir="ltr"><<a href="mailto:salva@unoyunodiez.com" target="_blank">salva@unoyunodiez.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<p dir="ltr">I think this did not reach the mailing list to the
W3:<br>
<a href="https://esdiscuss.org/topic/cancelable-promises#content-9" target="_blank">https://esdiscuss.org/topic/cancelable-promises#content-9</a></p>
<p dir="ltr">Actually the result cancellation is different from
promise cancellation. First is full of implementation details, thus
you are talking about smart cancellation. It is not smart, is the
only way to provide control, thus, the cancellationToken.</p>
<p dir="ltr">In the other side you're talking about "don't care"
what is actually related with the flow control. It turns out, after
a timeout, you are no longer interested in the result so you don't
use it because you don't care.</p>
<p dir="ltr">I insist, two concepts: one for cancelling a control
flow, another for an specific operation of the implementation.</p>
<div class="gmail_quote">El 02/03/2015 08:06, "Dean Tribble"
<<a href="mailto:tribble@e-dean.com" target="_blank">tribble@e-dean.com</a>> escribió:<br type="attribution">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<div class="h5">
<div dir="ltr">
<div><span style="font-size:12.8000001907349px">Another thread here
brought up the challenge of supporting cancellation in an async
environment. I spent some time on that particular challenge a few
years ago, and it turned out to be bigger and more interesting than
it appeared on the surface. In the another thread, Ron Buckton
pointed at the .Net approach and it's use in
JavaScript:</span></div>
<div><span style="font-size:12.8000001907349px"> </span></div>
<div>
<blockquote class="gmail_quote" style="color:rgb(80,0,80);font-size:12.8000001907349px;margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="font-family:Calibri,sans-serif;font-size:11pt">AsyncJS
(<a href="http://github.com/rbuckton/asyncjs" target="_blank">http://github.com/rbuckton/asyncjs</a>) uses a separate
abstraction for cancellation based on the .NET
CancellationTokenSource/CancellationToken types. You can find more
information about this abstraction in the MSDN documentation
here: <a href="https://msdn.microsoft.com/en-us/library/dd997364(v=vs.110).aspx" target="_blank">https://msdn.microsoft.com/en-us/library/dd997364(v=vs.110).aspx</a></div>
</blockquote>
</div>
<div><span style="font-size:12.8000001907349px"><span style="font-size:12.8000001907349px"><br></span></span></div>
It's great that asyncjs already has started using it. I was
surprised at how well the cancellationToken approach worked in both
small applications and when extended to a very large async system.
I'll summarize some of the architectural observations, especially
from extending it to async:
<div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><b>Cancel requests, not
results</b></div>
<div style="font-size:12.8000001907349px">Promises are like object
references for async; any particular promise might be returned or
passed to more than one client. Usually, programmers would be
surprised if a returned or passed in reference just got ripped out
from under them <i>by another client</i>. this is especially
obvious when considering a library that gets a promise passed into
it. Using "cancel" on the promise is like having delete on object
references; it's dangerous to use, and unreliable to have used by
others.</div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><b>Cancellation is
heterogeneous</b><br></div>
<div style="font-size:12.8000001907349px">It can be misleading to
think about canceling a single activity. In most systems, when
cancellation happens, many unrelated tasks may need to be cancelled
for the same reason. For example, if a user hits a stop button on a
large incremental query after they see the first few results, what
should happen?</div>
<div style="font-size:12.8000001907349px">
<ul>
<li style="margin-left:15px">the async fetch of more query results
should be terminated and the connection closed</li>
<li style="margin-left:15px">background computation to process the
remote results into renderable form should be stopped</li>
<li style="margin-left:15px">rendering of not-yet rendered content
should be stopped. this might include retrieval of secondary
content for the items no longer of interest (e.g., album covers for
the songs found by a complicated content search)</li>
<li style="margin-left:15px">the animation of "loading more" should
be stopped, and should be replaced with "user cancelled"</li>
<li style="margin-left:15px">etc.</li>
</ul>
</div>
<div style="font-size:12.8000001907349px">Some of these are
different levels of abstraction, and for any non-trivial
application, there isn't a single piece of code that can know to
terminate all these activities. This kind of system also requires
that cancellation support is consistent across many very different
types of components. But if each activity takes a
cancellationToken, in the above example, they just get passed the
one that would be cancelled if the user hits stop and the right
thing happens.</div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><b>Cancellation should be
smart</b><br></div>
<div style="font-size:12.8000001907349px">Libraries can and should
be smart about how they cancel. In the case of an async query, once
the result of a query from the server has come back, it may make
sense to finish parsing and caching it rather than just reflexively
discarding it. In the case of a brokerage system, for example, the
round trip to the servers to get recent data is the expensive part.
Once that's been kicked off and a result is coming back, having it
available in a local cache in case the user asks again is
efficient. If the application spawned another worker, it may be
more efficient to let the worker complete (so that you can reuse
it) rather than abruptly terminate it (requiring discarding of the
running worker and cached state).</div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><b>Cancellation is a
race</b><br></div>
<div style="font-size:12.8000001907349px">In an async system, new
activities may be getting continuously scheduled by asks that are
themselves scheduled but not currently running. The act of
cancelling needs to run in this environment. When cancel starts,
you can think of it as a signal racing out to catch up with all the
computations launched to achieve the now-cancelled objective. Some
of those may choose to complete (see the caching example above).
Some may potentially keep launching more work before that work
itself gets signaled (yeah it's a bug but people write buggy code).
In an async system, cancellation is not prompt. Thus, it's
infeasible to ask "has cancellation finished?" because that's not a
well defined state. Indeed, there can be code scheduled that should
and does not get cancelled (e.g., the result processor for a
pub/sub system), but that schedules work that will be cancelled
(parse the publication of an update to the now-cancelled
query). </div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><b>Cancellation is "don't
care"</b></div>
<div style="font-size:12.8000001907349px">Because smart
cancellation sometimes doesn't stop anything and in an async
environment, cancellation is racing with progress, it is at most
"best efforts". When a set of computations are cancelled, the party
canceling the activities is saying "I no longer care whether this
completes". That is importantly different from saying "I want to
prevent this from completing". The former is broadly usable
resource reduction. The latter is only usefully achieved in systems
with expensive engineering around atomicity and transactions. It
was amazing how much simpler cancellation logic becomes when it's
"don't care".</div>
<div style="font-size:12.8000001907349px"> <br></div>
<div style="font-size:12.8000001907349px"><b>Cancellation requires
separation of concerns</b></div>
<div style="font-size:12.8000001907349px">In the pattern where more
than one thing gets cancelled, the source of the cancellation is
rarely one of the things to be cancelled. It would be a surprise if
a library called for a cancellable activity (load this image)
cancelled an unrelated server query just because they cared about
the same cancellation event. I find it interesting that the
separation between cancellation token and cancellation source
mirrors that separation between a promise and it's resolver.</div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><b>Cancellation recovery
is transient</b></div>
<div style="font-size:12.8000001907349px">As a task progresses, the
cleanup action may change. In the example above, if the data table
requests more results upon scrolling, it's cancellation behavior
when there's an outstanding query for more data is likely to be
quite different than when it's got everything it needs displayed
for the current page. That's the reason why the "register" method
returns a capability to unregister the action.</div>
</div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px"><br></div>
<div style="font-size:12.8000001907349px">I don't want to derail
the other threads on the topic, but thought it useful to start
articulating some of the architectural background for a consistent
async cancellation architecture.</div>
</div>
<br></div>
</div>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
<br></blockquote>
</div>
<br>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
<br></blockquote>
</div>
<br></div>


_______________________________________________
<br>es-discuss mailing list
<br>es-discuss@mozilla.org
<br>https://mail.mozilla.org/listinfo/es-discuss
<br></div></div></span></blockquote></div><div class="bloop_markdown"><p></p></div></body></html>