Promise-returning delay function (original) (raw)

Spinning off a new thread...

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Mark S. Miller Subject: RE: "use strict" VS setTimeout

Let's just be sure that we avoid this mistake when promises grow something like Q's Q.delay. Promise.delay? Promise.prototype.delay?

IMO this should be a utility function that uses promises, not a feature of promises/promise classes themselves. So it would be e.g. global.delay or import delay from "js/flow" or something. I think in general promise utility functions are a slippery slope and I'd feel more comfortable sliding down that slope if we kept them in a module instead of grafting them onto the class itself. I'd rather reserve that for things that are core to the promise experience, either control-flow wise (Promise.prototype.finally, perhaps Promise.any) or for pipelining (.get, .call, etc.).

BTW I definitely agree that promise-returning delay(ms) as a better setTimeout should be part of the standard library.

(I also find the name sleep somewhat attractive, as a re-appropriation from threaded contexts. await sleep(1000), heh.)

Spinning off a new thread...

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Mark S. Miller Subject: RE: "use strict" VS setTimeout

Let's just be sure that we avoid this mistake when promises grow something like Q's Q.delay. Promise.delay? Promise.prototype.delay?

IMO this should be a utility function that uses promises, not a feature of promises/promise classes themselves. So it would be e.g. global.delay or import delay from "js/flow" or something. I think in general promise utility functions are a slippery slope and I'd feel more comfortable sliding down that slope if we kept them in a module instead of grafting them onto the class itself. I'd rather reserve that for things that are core to the promise experience, either control-flow wise (Promise.prototype.finally, perhaps Promise.any) or for pipelining (.get, .call, etc.).

BTW I definitely agree that promise-returning delay(ms) as a better setTimeout should be part of the standard library.

(I also find the name sleep somewhat attractive, as a re-appropriation from threaded contexts. await sleep(1000), heh.)

On 9 Sep 2014 00:13, "Domenic Denicola" <domenic at domenicdenicola.com> wrote:

(I also find the name sleep somewhat attractive, as a re-appropriation

from threaded contexts. await sleep(1000), heh.)

Sleep has blocking semantics in all languages I've used it in (eg. C, Java, Ruby, Bash, etc) so perhaps best avoid any confusion?

I've found delay very useful and natural in the context of Rx.Observables, where it is a method to delay each element in a stream, although that's a slightly different use case to what's proposed here.

What's the recommended way to add capabilities to Promises? Utility functions, as suggested here? Promise subclassing/"casting"? Prototype monkey patching (I guess not, but some will do that if there's no better way...)?

Reminds me from the elegant/surprising obj::func() binding syntax Domenic showed the other day in a presentation, too.

On 9 Sep 2014 00:13, "Domenic Denicola" wrote:

(I also find the name sleep somewhat attractive, as a re-appropriation from threaded contexts. await sleep(1000), heh.)

Sleep has blocking semantics in all languages I've used it in (eg. C, Java, Ruby, Bash, etc) so perhaps best avoid any confusion?

I've found delay very useful and natural in the context of Rx.Observables, where it is a method to delay each element in a stream, although that's a slightly different use case to what's proposed here.

What's the recommended way to add capabilities to Promises? Utility functions, as suggested here? Promise subclassing/"casting"? Prototype monkey patching (I guess not, but some will do that if there's no better way...)?

Reminds me from the elegant/surprising obj::func() binding syntax Domenic showed the other day in a presentation, too.

--


Visit theguardian.com. On your mobile and tablet, download the Guardian iPhone and Android apps theguardian.com/guardianapp and our tablet editions theguardian.com/editions. Save up to 57% by subscribing to the Guardian and Observer - choose the papers you want and get full digital access. Visit subscribe.theguardian.com

This e-mail and all attachments are confidential and may also be privileged. If you are not the named recipient, please notify the sender and delete the e-mail and all attachments immediately. Do not disclose the contents to another person. You may not use the information for any purpose, or store, or copy, it in any way. Guardian News & Media Limited is not liable for any computer viruses or other material transmitted with or as part of this e-mail. You should employ virus checking software.

Guardian News & Media Limited is a member of Guardian Media Group plc. Registered Office: PO Box 68164, Kings Place, 90 York Way, London, N1P 2AP. Registered in England Number 908396

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20140909/83e90ea7/attachment.html

The npm prfun package uses both prototypes patching and subclassing, fwiw. And it implements both Promise.delay andPromise.prototype.delay. I'd be interested in feedback after folks use it a bit.

The npm prfun package uses both prototypes patching and subclassing, fwiw. And it implements both Promise.delay and Promise.prototype.delay. I'd be interested in feedback after folks use it a bit. --scott On Sep 9, 2014 4:43 AM, "Sébastien Cevey" <seb.cevey at guardian.co.uk> wrote:

On 9 Sep 2014 00:13, "Domenic Denicola" wrote:

(I also find the name sleep somewhat attractive, as a re-appropriation from threaded contexts. await sleep(1000), heh.)

Sleep has blocking semantics in all languages I've used it in (eg. C, Java, Ruby, Bash, etc) so perhaps best avoid any confusion?

I've found delay very useful and natural in the context of Rx.Observables, where it is a method to delay each element in a stream, although that's a slightly different use case to what's proposed here.

What's the recommended way to add capabilities to Promises? Utility functions, as suggested here? Promise subclassing/"casting"? Prototype monkey patching (I guess not, but some will do that if there's no better way...)?

Reminds me from the elegant/surprising obj::func() binding syntax Domenic showed the other day in a presentation, too.


Visit theguardian.com. On your mobile and tablet, download the Guardian iPhone and Android apps theguardian.com/guardianapp and our tablet editions theguardian.com/editions. Save up to 57% by subscribing to the Guardian and Observer - choose the papers you want and get full digital access. Visit subscribe.theguardian.com

This e-mail and all attachments are confidential and may also be privileged. If you are not the named recipient, please notify the sender and delete the e-mail and all attachments immediately. Do not disclose the contents to another person. You may not use the information for any purpose, or store, or copy, it in any way. Guardian News & Media Limited is not liable for any computer viruses or other material transmitted with or as part of this e-mail. You should employ virus checking software.

Guardian News & Media Limited is a member of Guardian Media Group plc. Registered Office: PO Box 68164, Kings Place, 90 York Way, London, N1P 2AP. Registered in England Number 908396


es-discuss mailing list es-discuss at mozilla.org https://mail.mozilla.org/listinfo/es-discuss

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20140909/6fd61e1d/attachment.html

Domenic Denicola wrote:

BTW I definitely agree that promise-returning delay(ms) as a better setTimeout should be part of the standard library.

See twitter.com/garybernhardt/status/526435690524196864 where I'm subtweeted but with some justice. setTimeout began life taking only a program to eval, and given the general implicit-conversion mania afflicting me and others at Netscape, it converts its first argument to string source for that program. Only in Netscape 3 did the funarg-first form come in.

Sorry about that, and you're right -- at some promise-allocation and cognitive load costs, a new API could win. Another option is to have a new functional API, but I bet it won't be easy to name well or get approved.

Domenic Denicola wrote:

BTW I definitely agree that promise-returning delay(ms) as a better setTimeout should be part of the standard library.

See https://twitter.com/garybernhardt/status/526435690524196864 where I'm subtweeted but with some justice. setTimeout began life taking only a program to eval, and given the general implicit-conversion mania afflicting me and others at Netscape, it converts its first argument to string source for that program. Only in Netscape 3 did the funarg-first form come in.

Sorry about that, and you're right -- at some promise-allocation and cognitive load costs, a new API could win. Another option is to have a new functional API, but I bet it won't be easy to name well or get approved.

/be

Not sure if discussed already but I believe .cancel() or.forgetAboutIt() mechanism should be proposed before introducing any.delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Not sure if discussed already but I believe .cancel() or .forgetAboutIt() mechanism should be proposed before introducing any .delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Regards

On Mon, Oct 27, 2014 at 4:41 AM, Brendan Eich wrote:

Domenic Denicola wrote:

BTW I definitely agree that promise-returning delay(ms) as a better setTimeout should be part of the standard library.

See https://twitter.com/garybernhardt/status/526435690524196864 where I'm subtweeted but with some justice. setTimeout began life taking only a program to eval, and given the general implicit-conversion mania afflicting me and others at Netscape, it converts its first argument to string source for that program. Only in Netscape 3 did the funarg-first form come in.

Sorry about that, and you're right -- at some promise-allocation and cognitive load costs, a new API could win. Another option is to have a new functional API, but I bet it won't be easy to name well or get approved.

/be

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141027/b5aa9795/attachment-0001.html

On Mon, Oct 27, 2014 at 3:21 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

Not sure if discussed already but I believe .cancel() or.forgetAboutIt() mechanism should be proposed before introducing any.delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Cancelable promises are a completely different beast; it's not just a matter of adding a new method to Promise.prototype, it's changing the data structure pretty fundamentally. Suddenly you have a new value-affecting capability, but it's exposed outside of the constructor. You need to be able to react to a cancellation, so you can actually cancel the work being done, and possibly resolve the promise to some default value (or error).

A promise that auto-resolves after a timeout, on the other hand, is a straightforward utility function of obvious usefulness, and requires no additional work:

Promise.delay = function(ms) { return new Promise(function(r) { setTimeout(r, ms); }); }

(Not tested, but this should be approximately right.)

On Mon, Oct 27, 2014 at 3:21 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

Not sure if discussed already but I believe .cancel() or .forgetAboutIt() mechanism should be proposed before introducing any .delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Cancelable promises are a completely different beast; it's not just a matter of adding a new method to Promise.prototype, it's changing the data structure pretty fundamentally. Suddenly you have a new value-affecting capability, but it's exposed outside of the constructor. You need to be able to react to a cancellation, so you can actually cancel the work being done, and possibly resolve the promise to some default value (or error).

A promise that auto-resolves after a timeout, on the other hand, is a straightforward utility function of obvious usefulness, and requires no additional work:

Promise.delay = function(ms) { return new Promise(function(r) { setTimeout(r, ms); }); }

(Not tested, but this should be approximately right.)

~TJ

I thought promises were introduced to simply the "whenever it happens" pattern ... using a delay seems a pretty pointless feature to me and setTimeout worked so far (15 years?) pretty well and it is cancelable.

Regardless delay though, canceling, beast or not, should be considered before all these changes will make it "impossible" to implement, IMO

I thought promises were introduced to simply the "whenever it happens" pattern ... using a delay seems a pretty pointless feature to me and setTimeout worked so far (15 years?) pretty well and it is cancelable.

Regardless delay though, canceling, beast or not, should be considered before all these changes will make it "impossible" to implement, IMO

On Mon, Oct 27, 2014 at 2:52 PM, Tab Atkins Jr. wrote:

On Mon, Oct 27, 2014 at 3:21 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

Not sure if discussed already but I believe .cancel() or .forgetAboutIt() mechanism should be proposed before introducing any .delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Cancelable promises are a completely different beast; it's not just a matter of adding a new method to Promise.prototype, it's changing the data structure pretty fundamentally. Suddenly you have a new value-affecting capability, but it's exposed outside of the constructor. You need to be able to react to a cancellation, so you can actually cancel the work being done, and possibly resolve the promise to some default value (or error).

A promise that auto-resolves after a timeout, on the other hand, is a straightforward utility function of obvious usefulness, and requires no additional work:

Promise.delay = function(ms) { return new Promise(function(r) { setTimeout(r, ms); }); }

(Not tested, but this should be approximately right.)

~TJ

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141027/1071814c/attachment.html

There's already a way to cancel a Promise -- use its reject function. eg.

var reject;
Promise.delay(100/*ms*/).then(function() { reject(new Error('took too
long')); });
return new Promise(function(resolve, _reject) {
  reject = _reject;
  resolve(doSomethingTimeConsuming());
});

There's no need to rethink or redesign anything.

See cscott/prfun#promisetimeoutint-ms--string-message--promisefor a nice example, borrowed from bluebird.

There's already a way to cancel a Promise -- use its reject function. eg.

var reject;
Promise.delay(100/*ms*/).then(function() { reject(new Error('took too
long')); });
return new Promise(function(resolve, _reject) {
  reject = _reject;
  resolve(doSomethingTimeConsuming());
});

There's no need to rethink or redesign anything.

See https://github.com/cscott/prfun#promisetimeoutint-ms--string-message--promise for a nice example, borrowed from bluebird. --scott

On Mon, Oct 27, 2014 at 3:20 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

I thought promises were introduced to simply the "whenever it happens" pattern ... using a delay seems a pretty pointless feature to me and setTimeout worked so far (15 years?) pretty well and it is cancelable.

Regardless delay though, canceling, beast or not, should be considered before all these changes will make it "impossible" to implement, IMO

On Mon, Oct 27, 2014 at 2:52 PM, Tab Atkins Jr. wrote:

On Mon, Oct 27, 2014 at 3:21 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

Not sure if discussed already but I believe .cancel() or .forgetAboutIt() mechanism should be proposed before introducing any .delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Cancelable promises are a completely different beast; it's not just a matter of adding a new method to Promise.prototype, it's changing the data structure pretty fundamentally. Suddenly you have a new value-affecting capability, but it's exposed outside of the constructor. You need to be able to react to a cancellation, so you can actually cancel the work being done, and possibly resolve the promise to some default value (or error).

A promise that auto-resolves after a timeout, on the other hand, is a straightforward utility function of obvious usefulness, and requires no additional work:

Promise.delay = function(ms) { return new Promise(function(r) { setTimeout(r, ms); }); }

(Not tested, but this should be approximately right.)

~TJ


es-discuss mailing list es-discuss at mozilla.org https://mail.mozilla.org/listinfo/es-discuss

canceling should not pass through any errorback chain... Canceling is like an explicit abort on xhr ... Not an error, not a fulfillment, it's a third state: cancelled

canceling should not pass through any errorback chain... Canceling is like an explicit abort on xhr ... Not an error, not a fulfillment, it's a third state: cancelled

-----Original Message----- From: "C. Scott Ananian" Sent: ‎27/‎10/‎2014 19:39 To: "Andrea Giammarchi" <andrea.giammarchi at gmail.com> Cc: "Tab Atkins Jr." ; "Mark S. Miller" ; "Domenic Denicola" ; "Mark Miller" ; "es-discuss list" Subject: Re: Promise-returning delay function

There's already a way to cancel a Promise -- use its reject function. eg.

var reject;
Promise.delay(100/*ms*/).then(function() { reject(new Error('took too
long')); });
return new Promise(function(resolve, _reject) {
  reject = _reject;
  resolve(doSomethingTimeConsuming());
});

There's no need to rethink or redesign anything.

See https://github.com/cscott/prfun#promisetimeoutint-ms--string-message--promise for a nice example, borrowed from bluebird. --scott

On Mon, Oct 27, 2014 at 3:20 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

I thought promises were introduced to simply the "whenever it happens" pattern ... using a delay seems a pretty pointless feature to me and setTimeout worked so far (15 years?) pretty well and it is cancelable.

Regardless delay though, canceling, beast or not, should be considered before all these changes will make it "impossible" to implement, IMO

On Mon, Oct 27, 2014 at 2:52 PM, Tab Atkins Jr. wrote:

On Mon, Oct 27, 2014 at 3:21 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

Not sure if discussed already but I believe .cancel() or .forgetAboutIt() mechanism should be proposed before introducing any .delay()

Promises often put developers in unmanaged roads where things keep being "forgotten" and/or impossible to drop without ending up in the next chain, undesired, or the error stack, even less desired.

What I mean is that if setTimeout is a desired pattern to replicate through .delay(ms), but I really don't understand why that would be a desired pattern at all, clearTimeout functionality should be considered as well.

A generic .cancel() would be most likely the easier approach but it should be implemented upfront.

Cancelable promises are a completely different beast; it's not just a matter of adding a new method to Promise.prototype, it's changing the data structure pretty fundamentally. Suddenly you have a new value-affecting capability, but it's exposed outside of the constructor. You need to be able to react to a cancellation, so you can actually cancel the work being done, and possibly resolve the promise to some default value (or error).

A promise that auto-resolves after a timeout, on the other hand, is a straightforward utility function of obvious usefulness, and requires no additional work:

Promise.delay = function(ms) { return new Promise(function(r) { setTimeout(r, ms); }); }

(Not tested, but this should be approximately right.)

~TJ


es-discuss mailing list es-discuss at mozilla.org https://mail.mozilla.org/listinfo/es-discuss

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/04a28de0/attachment-0001.html

So throw a different class of Error, or resolve with a different type of object. Can you substantiate your assertion better?

In my experience, regularity of control flow constructs is a feature, not a bug. I don't want to have to reason about some "third way" control flow.

So throw a different class of Error, or resolve with a different type of object. Can you substantiate your assertion better?

In my experience, regularity of control flow constructs is a feature, not a bug. I don't want to have to reason about some "third way" control flow. --scott -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/3719252a/attachment.html

The moment you pass a promise you have no control on who's adding what as callback or errorback which means you have no control over a .reject() or over a .success()

.cancel() would eventually keep both queues unresolved so that nothing should happen at all: no error handling, no error happened, and no actions needed ... it's simply canceled.

This is the same reason .fetch() API needs also events to work properly (including progress) ... you "cannot" base as example typeahead on promises right now 'cause it's a mess to handle since response order is not guaranteed but you need to handle the .cancel() case without telling the user something else went wrong ... what you suggest, a new Noop() whereNoop.prototype = Object.create(Error.prototype) ?

And how do you instruct unknown surrounding code that an if (err instanceof Noop) should be the first line of every errback ?

This is the reason few devs cannot adopt current standard Promises.

.cancel() as well as .abort() is very important when many network operations are in place and/or you want to switch to a different state without waiting for the previous one to be fulfilled.

new Promise(function (resolve, reject, cancel) {}); is the dumbest idea I could have now beside new Promise(function (resolve, reject) {}).on('cancel', cancelback).then(whatever) one

Anyway, this would deserve IMO a thread a part but I hope this topic will be discussed at some point.

Best

The moment you pass a promise you have no control on who's adding what as callback or errorback which means you have no control over a .reject() or over a .success()

.cancel() would eventually keep both queues unresolved so that nothing should happen at all: no error handling, no error happened, and no actions needed ... it's simply canceled.

This is the same reason .fetch() API needs also events to work properly (including progress) ... you "cannot" base as example typeahead on promises right now 'cause it's a mess to handle since response order is not guaranteed but you need to handle the .cancel() case without telling the user something else went wrong ... what you suggest, a new Noop() where Noop.prototype = Object.create(Error.prototype) ?

And how do you instruct unknown surrounding code that an if (err instanceof Noop) should be the first line of every errback ?

This is the reason few devs cannot adopt current standard Promises.

.cancel() as well as .abort() is very important when many network operations are in place and/or you want to switch to a different state without waiting for the previous one to be fulfilled.

new Promise(function (resolve, reject, cancel) {}); is the dumbest idea I could have now beside new Promise(function (resolve, reject) {}).on('cancel', cancelback).then(whatever) one

Anyway, this would deserve IMO a thread a part but I hope this topic will be discussed at some point.

Best Regards

On Tue, Oct 28, 2014 at 2:13 PM, C. Scott Ananian wrote:

So throw a different class of Error, or resolve with a different type of object. Can you substantiate your assertion better?

In my experience, regularity of control flow constructs is a feature, not a bug. I don't want to have to reason about some "third way" control flow. --scott

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/19b80c30/attachment.html

On Tue, Oct 28, 2014 at 10:41 AM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

The moment you pass a promise you have no control on who's adding what as callback or errorback which means you have no control over a .reject() or over a .success()

.cancel() would eventually keep both queues unresolved so that nothing should happen at all: no error handling, no error happened, and no actions needed ... it's simply canceled.

This is the same reason .fetch() API needs also events to work properly (including progress) ... you "cannot" base as example typeahead on promises right now 'cause it's a mess to handle since response order is not guaranteed but you need to handle the .cancel() case without telling the user something else went wrong ... what you suggest, a new Noop() whereNoop.prototype = Object.create(Error.prototype) ?

And how do you instruct unknown surrounding code that an if (err instanceof Noop) should be the first line of every errback ?

This is the reason few devs cannot adopt current standard Promises.

.cancel() as well as .abort() is very important when many network operations are in place and/or you want to switch to a different state without waiting for the previous one to be fulfilled.

new Promise(function (resolve, reject, cancel) {}); is the dumbest idea I could have now beside new Promise(function (resolve, reject) {}).on('cancel', cancelback).then(whatever) one

Anyway, this would deserve IMO a thread a part but I hope this topic will be discussed at some point.

Best

I agree w/ Scott re: regularity of flow control, and I'd be particularly uneasy if a cancel method on a promise had any impact on upstream handlers. But ISTM something like this could be made to work (even if it looks a bit silly):

var cancelled;
var never = new Promise(function () {});
Promise.delay(100/*ms*/).then(function(value) {
    return cancelled ? never : value;
}, function (error) {
    return cancelled ? never : throw error;
});
function cancel() { cancel = true };

This could be cleaned up into a cancellation helper to quash downstream promises (this kind of utility would be a good use case for an alwaysmethod if one isn't yet spec'd).

Though I do wonder what happens to promises like these that get dropped on the floor? Will downstream handlers be GC'd? Is this specified in any way? I imagine dev tools want to warn about these kinds of promises — it may be helpful to have a way to signal that a promise was intentionally quashed.

On Tue, Oct 28, 2014 at 10:41 AM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

The moment you pass a promise you have no control on who's adding what as callback or errorback which means you have no control over a .reject() or over a .success()

.cancel() would eventually keep both queues unresolved so that nothing should happen at all: no error handling, no error happened, and no actions needed ... it's simply canceled.

This is the same reason .fetch() API needs also events to work properly (including progress) ... you "cannot" base as example typeahead on promises right now 'cause it's a mess to handle since response order is not guaranteed but you need to handle the .cancel() case without telling the user something else went wrong ... what you suggest, a new Noop() where Noop.prototype = Object.create(Error.prototype) ?

And how do you instruct unknown surrounding code that an if (err instanceof Noop) should be the first line of every errback ?

This is the reason few devs cannot adopt current standard Promises.

.cancel() as well as .abort() is very important when many network operations are in place and/or you want to switch to a different state without waiting for the previous one to be fulfilled.

new Promise(function (resolve, reject, cancel) {}); is the dumbest idea I could have now beside new Promise(function (resolve, reject) {}).on('cancel', cancelback).then(whatever) one

Anyway, this would deserve IMO a thread a part but I hope this topic will be discussed at some point.

Best Regards

I agree w/ Scott re: regularity of flow control, and I'd be particularly uneasy if a cancel method on a promise had any impact on upstream handlers. But ISTM something like this could be made to work (even if it looks a bit silly):

var cancelled;
var never = new Promise(function () {});
Promise.delay(100/*ms*/).then(function(value) {
    return cancelled ? never : value;
}, function (error) {
    return cancelled ? never : throw error;
});
function cancel() { cancel = true };

This could be cleaned up into a cancellation helper to quash downstream promises (this kind of utility would be a good use case for an always method if one isn't yet spec'd).

Though I do wonder what happens to promises like these that get dropped on the floor? Will downstream handlers be GC'd? Is this specified in any way? I imagine dev tools want to warn about these kinds of promises — it may be helpful to have a way to signal that a promise was intentionally quashed. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/d2ef60f3/attachment.html

You probably want streams for typeahead, not promises.

You probably want streams for typeahead, not promises. --scott

Dean, your idea is even better as a Promise subclass.

The subclassed cancellable promises could share a cancel flag, and throw an exception (or resolve to a different value, whichever you like better for the API) when the cancel flag is set. The thenmethod on CancellablePromise returns another CancellablePromise(the spec is nicely written this way), and you use Promise.resolveto cast to a standard Promise to end the cancellation chain at an appropriate place.

See the Promise.bind implementation in prfun for an example of using subclasses in this way:cscott/prfun/blob/master/lib/index.js#L518--scott

ps. Of course, to be precise, your API would be a factory function which makes a new subclass of CancellablePromise for each cancel scope, since the Promise spec associates the state with the constructor identity. (I had some small issues with the "new subclass for each X" mechanism in an earlier attempt at creating MonadicPromise using subclasses, but I think these were ultimately resolved in the spec---and in that case I was creating a new subclass for each call toPromise.resolve, which was a whole 'nuther kettle of fish.)

Dean, your idea is even better as a Promise subclass.

The subclassed cancellable promises could share a cancel flag, and throw an exception (or resolve to a different value, whichever you like better for the API) when the cancel flag is set. The then method on CancellablePromise returns another CancellablePromise (the spec is nicely written this way), and you use Promise.resolve to cast to a standard Promise to end the cancellation chain at an appropriate place.

See the Promise.bind implementation in prfun for an example of using subclasses in this way: https://github.com/cscott/prfun/blob/master/lib/index.js#L518 --scott

ps. Of course, to be precise, your API would be a factory function which makes a new subclass of CancellablePromise for each cancel scope, since the Promise spec associates the state with the constructor identity. (I had some small issues with the "new subclass for each X" mechanism in an earlier attempt at creating MonadicPromise using subclasses, but I think these were ultimately resolved in the spec---and in that case I was creating a new subclass for each call to Promise.resolve, which was a whole 'nuther kettle of fish.)

On Tue, Oct 28, 2014 at 11:21 AM, Dean Landolt wrote:

On Tue, Oct 28, 2014 at 10:41 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

The moment you pass a promise you have no control on who's adding what as callback or errorback which means you have no control over a .reject() or over a .success()

.cancel() would eventually keep both queues unresolved so that nothing should happen at all: no error handling, no error happened, and no actions needed ... it's simply canceled.

This is the same reason .fetch() API needs also events to work properly (including progress) ... you "cannot" base as example typeahead on promises right now 'cause it's a mess to handle since response order is not guaranteed but you need to handle the .cancel() case without telling the user something else went wrong ... what you suggest, a new Noop() where Noop.prototype = Object.create(Error.prototype) ?

And how do you instruct unknown surrounding code that an if (err instanceof Noop) should be the first line of every errback ?

This is the reason few devs cannot adopt current standard Promises.

.cancel() as well as .abort() is very important when many network operations are in place and/or you want to switch to a different state without waiting for the previous one to be fulfilled.

new Promise(function (resolve, reject, cancel) {}); is the dumbest idea I could have now beside new Promise(function (resolve, reject) {}).on('cancel', cancelback).then(whatever) one

Anyway, this would deserve IMO a thread a part but I hope this topic will be discussed at some point.

Best Regards

I agree w/ Scott re: regularity of flow control, and I'd be particularly uneasy if a cancel method on a promise had any impact on upstream handlers. But ISTM something like this could be made to work (even if it looks a bit silly):

var cancelled;
var never = new Promise(function () {});
Promise.delay(100/*ms*/).then(function(value) {
    return cancelled ? never : value;
}, function (error) {
    return cancelled ? never : throw error;
});
function cancel() { cancel = true };

This could be cleaned up into a cancellation helper to quash downstream promises (this kind of utility would be a good use case for an always method if one isn't yet spec'd).

Though I do wonder what happens to promises like these that get dropped on the floor? Will downstream handlers be GC'd? Is this specified in any way? I imagine dev tools want to warn about these kinds of promises — it may be helpful to have a way to signal that a promise was intentionally quashed.

I actually don't want Promises at all with network interactions but you have to explain this to all developers out there that think Promises are the Eldorado for everything asynchronous ... I found myself needing a cancel mechanism that goes beyond your outer scoped flag.

I really need to drop that action ... not to wait for it to fulfill and then do something else.

Imagine it's not about network, imagine it's "a lift" ... door are closing, someone passes in the middle, what do you do now: sound the alert after chopping the person that tried to enter in the meanwhile or change floor ... after chopping the person anyway ?

If promises could handle edge cases events too I think we could handle above situation instead of chopping that poor person.

I hope you got what I mean but again this most likely need another thread.

Best

I actually don't want Promises at all with network interactions but you have to explain this to all developers out there that think Promises are the Eldorado for everything asynchronous ... I found myself needing a cancel mechanism that goes beyond your outer scoped flag.

I really need to drop that action ... not to wait for it to fulfill and then do something else.

Imagine it's not about network, imagine it's "a lift" ... door are closing, someone passes in the middle, what do you do now: sound the alert after chopping the person that tried to enter in the meanwhile or change floor ... after chopping the person anyway ?

If promises could handle edge cases events too I think we could handle above situation instead of chopping that poor person.

I hope you got what I mean but again this most likely need another thread.

Best Regards

On Tue, Oct 28, 2014 at 3:21 PM, C. Scott Ananian wrote:

You probably want streams for typeahead, not promises. --scott

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/71e5a164/attachment-0001.html

On Tue, Oct 28, 2014 at 2:24 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

I really need to drop that action ... not to wait for it to fulfill and then do something else.

This is orthogonal to the use of Promises, which just discuss control flow.

Imagine it's not about network, imagine it's "a lift" ... door are closing, someone passes in the middle, what do you do now: sound the alert after chopping the person that tried to enter in the meanwhile or change floor ... after chopping the person anyway ?

You call the Door.interrupt() API method to indicate that a person is present/cancel the opening.

Again, this is orthogonal to the Promise that the Door.close()method returned. If Door.close() returned a Promise, then that promise could then resolve to "cancelled" value (instead of "success"), or else you could decide that rejecting the promise with aDoorCloseInterrupted exception makes more sense.

The asynchronous cancellation mechanism is not related to Promises, and shouldn't be conflated with the Promise API. The Promise mechanism just directs control flow after the door has either been successfully closed or cancelled.

Concretely:

function tryToAscend() {
return Door.close().then(function() { return raiseLift(); },
function(e) { return Door.open().delay(10*1000).then(tryToAscend); });
};

On Tue, Oct 28, 2014 at 2:24 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

I really need to drop that action ... not to wait for it to fulfill and then do something else.

This is orthogonal to the use of Promises, which just discuss control flow.

Imagine it's not about network, imagine it's "a lift" ... door are closing, someone passes in the middle, what do you do now: sound the alert after chopping the person that tried to enter in the meanwhile or change floor ... after chopping the person anyway ?

You call the Door.interrupt() API method to indicate that a person is present/cancel the opening.

Again, this is orthogonal to the Promise that the Door.close() method returned. If Door.close() returned a Promise, then that promise could then resolve to "cancelled" value (instead of "success"), or else you could decide that rejecting the promise with a DoorCloseInterrupted exception makes more sense.

The asynchronous cancellation mechanism is not related to Promises, and shouldn't be conflated with the Promise API. The Promise mechanism just directs control flow after the door has either been successfully closed or cancelled.

Concretely:

function tryToAscend() {
return Door.close().then(function() { return raiseLift(); },
function(e) { return Door.open().delay(10*1000).then(tryToAscend); });
};

--scott

Again, you might have an error that comes from "ringTheAlarmBell()" API ... you are making the problem simple but simple is not the moment all you do is returning a Promise with binary result (success/error) without considering that when you reopen, much more could happen ... you wantto branch out, not keeping doing the same action and that error could come for many reasons.

Your control flow here, if you have to take care of all cases, will become a mess full of nested callbacks ... oh, irony

Again, you might have an error that comes from "ringTheAlarmBell()" API ... you are making the problem simple but simple is not the moment all you do is returning a Promise with binary result (success/error) without considering that when you reopen, much more could happen ... you want to branch out, not keeping doing the same action and that error could come for many reasons.

Your control flow here, if you have to take care of all cases, will become a mess full of nested callbacks ... oh, irony

On Tue, Oct 28, 2014 at 7:39 PM, C. Scott Ananian wrote:

On Tue, Oct 28, 2014 at 2:24 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

I really need to drop that action ... not to wait for it to fulfill and then do something else.

This is orthogonal to the use of Promises, which just discuss control flow.

Imagine it's not about network, imagine it's "a lift" ... door are closing, someone passes in the middle, what do you do now: sound the alert after chopping the person that tried to enter in the meanwhile or change floor ... after chopping the person anyway ?

You call the Door.interrupt() API method to indicate that a person is present/cancel the opening.

Again, this is orthogonal to the Promise that the Door.close() method returned. If Door.close() returned a Promise, then that promise could then resolve to "cancelled" value (instead of "success"), or else you could decide that rejecting the promise with a DoorCloseInterrupted exception makes more sense.

The asynchronous cancellation mechanism is not related to Promises, and shouldn't be conflated with the Promise API. The Promise mechanism just directs control flow after the door has either been successfully closed or cancelled.

Concretely:

function tryToAscend() {
return Door.close().then(function() { return raiseLift(); },
function(e) { return Door.open().delay(10*1000).then(tryToAscend); });
};

--scott

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/84ce28ea/attachment-0001.html

I don't see any evidence that you can't handle the various cases with the usual control flow mechanisms. Remember that promises are isomorphic to the future async/await syntax.

I don't see any evidence that you can't handle the various cases with the usual control flow mechanisms. Remember that promises are isomorphic to the future async/await syntax. --scott

async and await would fail here same way indeed, there should be a mechanism to branch out the binary expected result, IMO.

The other thread and the fact .NET already has something similar should probably ring some bell but it's probably there that we should discuss this.

async and await would fail here same way indeed, there should be a mechanism to branch out the binary expected result, IMO.

The other thread and the fact .NET already has something similar should probably ring some bell but it's probably there that we should discuss this.

Regards

On Tue, Oct 28, 2014 at 10:12 PM, C. Scott Ananian wrote:

I don't see any evidence that you can't handle the various cases with the usual control flow mechanisms. Remember that promises are isomorphic to the future async/await syntax. --scott

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/24edcb6a/attachment.html

Again, I don't see how this requires some new sort of control flow.

Again, I don't see how this requires some new sort of control flow. --scott

try to put a cancel in your same code:

function tryToAscend() {
return Door.close().then(function() { return raiseLift(); },
function(e) { return Door.open().delay(10*1000).then(tryToAscend); });
};

because when the door opens somebody cancel the floor and wants to descend instead.

Then implement the case when actually the call was simply canceled and nobody has to go anywhere ... all while delay keeps saying to each floor that after 10 seconds doors should close anyway.

Now try to pass this glorious flow around per each panel in each floor that should behave accordingly.

Can you do this via Promises? 'cause I'm pretty sure that code won't look any better than an event based one, but I can be wrong.

try to put a cancel in your same code:

function tryToAscend() {
return Door.close().then(function() { return raiseLift(); },
function(e) { return Door.open().delay(10*1000).then(tryToAscend); });
};

because when the door opens somebody cancel the floor and wants to descend instead.

Then implement the case when actually the call was simply canceled and nobody has to go anywhere ... all while delay keeps saying to each floor that after 10 seconds doors should close anyway.

Now try to pass this glorious flow around per each panel in each floor that should behave accordingly.

Can you do this via Promises? 'cause I'm pretty sure that code won't look any better than an event based one, but I can be wrong.

Regards

On Tue, Oct 28, 2014 at 10:30 PM, C. Scott Ananian wrote:

Again, I don't see how this requires some new sort of control flow. --scott

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20141028/c9354580/attachment-0001.html

Follow up on esdiscuss.org/topic/promise-returning-delay-function

I think we really need that function, with AbortController support

We could do things like

const abortFetch = new AbortController();
const abortTimeout = new AbortController();

await Promise.race([
  Promise.delay(5000, {signal: abortTimeout.signal}),
  fetch(url, {signal: abortFetch.signal}).then(r => r.json()).then(...),
])
  .finally(() => {
    abortFetch.abort();
    abortTimeout.abort(); // avoid mem leaks, that would call clearTimeout
under the hood
  })

Follow up on https://esdiscuss.org/topic/promise-returning-delay-function

I think we really need that function, with AbortController support

We could do things like

const abortFetch = new AbortController();
const abortTimeout = new AbortController();

await Promise.race([
  Promise.delay(5000, {signal: abortTimeout.signal}),
  fetch(url, {signal: abortFetch.signal}).then(r => r.json()).then(...),
])
  .finally(() => {
    abortFetch.abort();
    abortTimeout.abort(); // avoid mem leaks, that would call clearTimeout
under the hood
  })

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20201227/2b0fd72b/attachment.html

For Node.js we implemented this as an alternative to the current setTimeout:

const { setTimeout } = require('timers/promises')

// Or

import { setTimeout } from 'timers/promises'

Then...

await setTimeout(500)

It works very well and is straightforward to implement on the browser-side.

For Node.js we implemented this as an alternative to the current setTimeout:

const { setTimeout } = require('timers/promises')

// Or

import { setTimeout } from 'timers/promises'

Then...

await setTimeout(500)

It works very well and is straightforward to implement on the browser-side.

On Sun, Dec 27, 2020, 09:56 Cyril Auburtin <cyril.auburtin at gmail.com> wrote:

Follow up on https://esdiscuss.org/topic/promise-returning-delay-function

I think we really need that function, with AbortController support

We could do things like

const abortFetch = new AbortController();
const abortTimeout = new AbortController();

await Promise.race([
  Promise.delay(5000, {signal: abortTimeout.signal}),
  fetch(url, {signal: abortFetch.signal}).then(r => r.json()).then(...),
])
  .finally(() => {
    abortFetch.abort();
    abortTimeout.abort(); // avoid mem leaks, that would call clearTimeout
under the hood
  })

es-discuss mailing list es-discuss at mozilla.org https://mail.mozilla.org/listinfo/es-discuss

-------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20201227/c2606fff/attachment.html