Giter Club home page Giter Club logo

promises-spec's People

Contributors

andot avatar briancavalier avatar chunpu avatar commanderq avatar domenic avatar evangoer avatar fastner avatar fidian avatar forbeslindesay avatar gobwas avatar iam91 avatar listenlin avatar loveky avatar lsmith avatar mgol avatar mohawk2 avatar msrose avatar mudge avatar novemberborn avatar ondras avatar petkaantonov avatar plvhx avatar potch avatar rkatic avatar ronnewcomb avatar rousan avatar rwstauner avatar stopsopa avatar vilicvane avatar xieranmaya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

promises-spec's Issues

Small clarification on what is a legal value

The spec says

  • a “value” is any legal language value, including undefined, that is not a promise
  • A promise is an object or function that defines a then method that accepts [...] two arguments [which must follow this specification]...

and specifies that a callback has different behavior depending on whether a value or a promise is returned.

I might attempt to construct what I think would be a legal value:

{
  "at": function () {},
  "from": function () {},
  "then": function() {},
  "was": function() {}
}

which I think is not a promise because it doesn't meet the requirements to make it a conforming promise; and since it's not a promise then it should be a legal value.

Of course one couldn't expect an implementation to inspect my object to see that it wasn't a conforming promise... so for clarity it would be useful to say something like a value is "any legal language value... that is not an object with a then property which is callable."

Status of setImmediate development

Hi guys! It feels weird opening a bug for this. Should we create a mailing list instead?

Anyway, I don't know if you've seen me post this on Twitter, but it seems that development for setImmediate is far from active. Only Microsoft has an implementation. Please take a look at this bugs and consider adding arguments for why setImmediate is useful.

Chrome

http://code.google.com/p/chromium/issues/detail?id=146172&can=1&q=setImmediate&colspec=ID%20Pri%20Mstone%20ReleaseBlock%20OS%20Area%20Feature%20Status%20Owner%20Summary

Firefox

https://bugzilla.mozilla.org/show_bug.cgi?id=686201

Companion specs

I've seen mentions of a Resolvers/A+, and @ForbesLindesay mentioned the following in #43:

I'll accept it as not part of this spec, but I think it should be part of the near future. I personally think we should aim to specify as many of the methods that often appear on promises implementations as possible, one at a time in separate spec's.

Personally I'd like to write proposals on cancelation, state inspection and progress propagation, ideally under the @promises-aplus umbrella. What would be the best way of achieving this? Different repositories? Multiple documents in this repository? And with those specs we should write a test suite like https://github.com/promises-aplus/promises-tests. Where would that go?

State definitions suggest separate, unspec'd method to access value/reason

  1. In the fulfilled state, a promise
    1. must have a value, which must not change.
    2. must provide a way to arrange for a function to be called with that value.

This section precedes the definition of then, but nothing in the spec suggests that then should be the function alluded to. This should be clarified or footnoted that then can be used, but implementations may include other methods to access the value synchronously.

Unspecified behavior when `onFulfilled` or `onRejected` throws a promise object

Per my note on issue 7 of the resolvers spec, the spec language for 3.2.6.2 says

If either onFulfilled or onRejected throws an exception, promise2 must be rejected with the thrown exception as the reason.

But "exception" isn't defined, so

promise.then(function () {
    throw otherPromise;
}).then(what?);

is possible.

It's edge case city, but it is a loophole that could be considered a legal way of passing a promise as a value between callbacks (besides return [otherPromise]). Otherwise, it's an opportunity for implementation iniquity, and my guess would be that Unexpected Things are bound to happen in the pass-through mechanism when subsequent onRejected callbacks aren't supplied.

Add info about non-interference of handlers

I had a twitter convo today with someone who couldn't tell from the current spec whether one handler could prevent another from being executed. For example, he was unsure if f2 would be executed in this scenario:

// let p1 be a fulfilled promise
p1.then(function f1() { throw new Error(); });
p1.then(function f2() {});

My feeling is that 3.2.2, 3.2.3, and 3.2.5.x are sufficient, and I pointed him to those. He still felt it wasn't obvious, so I wanted to pass along his concern to see whether others feel we should add something to clarify.

Write a version using ES-style spec language

Inspired by #44 (comment) I think it'd be a fun exercise to create a second version of the spec that is written in the obtuse-but-specific style of the ECMAScript spec itself.

This seems likely to draw out underspecified or unspecified portions, by forcing us to think more specifically about the exact language operations going on.

Feel free to close if you think this shoudn't be part of the A+ effort per se, but instead a fun side project that I do on my own time.

Tag 1.0.0

Quick straw pull: Are we ready for 1.0.0? 👍 or 👎

If 👎 then please list the specific reasons.

can a promise yield multiple values?

I don't see any apparent reason why a fulfillment/rejection can not produce multiple values.

promise.fulfill(1,2,3).then(function(a,b,c){console.log(a,b,c)});

Is this bad, if so why ? :)

Assimilating thenables-for-promises

See promises-aplus/promises-tests#20, wherein we essentially have this situation:

var fulfilledPromise = makeFulfilledPromiseFor(5);
var thenableForFulfilled = {
  then: function (f, r) {
    f(fulfilledPromise);
  }
};
var assimilatedThenable = makeFulfilledPromiseFor("whatever").then(function () {
  return thenableForFulfilled;
});

// What should happen here?
assimilatedThenable.then(function (value) {
  // should `value === 5` or `value === fulfilledPromise`???
});

I think the reading of the current spec is that value === fulfilledPromise. As I said over there:

When attempting to adopt thenableForFulfilled's state, you can only rely on the then method, which is clearly telling you that it's fulfilled with fulfilledPromise. In particular, it's not telling you thenableForFulfilled is waiting on fulfilledPromise; if that were the case, it wouldn't call you back immediately.


Is this OK? Are there sane wording changes to the current spec that would allow us to have value === 5, which is probably more desirable? (Or should we just respect thenableForFulfilled's wishes?)

What do current implementations do? Apparently WinJS.Promise does value === 5.

Reserve .then() 3rd argument for progress handling

From #1

Reserving .then()'s 3rd argument for progress. I'm open to it, but also not sure of the best way to do this ... something like ".then() may accept a 3rd argument that is for future capabilities not yet specified here" sounds kind of odd. Suggestions?

Specifying (or not) sync/async resolution behavior

From #1

Without getting into which is "better", I think the more important initial question is:

Does such a requirement actually belong in this proposal?

There are quality implementations of Promises/A in the wild that do each, and in my experience, they interoperate without problems. For example, I have mixed when.js, Dojo Deferred, jQuery Deferred, and Q in real, deployed applications over the past 2 years, and have never had a problem that I could attribute to one of them not doing async resolutions.

So, I think we need to answer the question of whether this belongs in the spec or not before we can discuss the obvious follow-on question :)

Should we spec "resolution races"?

I.e., should we say that, while in the fulfilled or rejected state, attempting to transition to the other state should fail silently, not noisily?

This is probably out of scope, since we don't spec mechanisms to change state, but I thought I'd bring it up, since we do require that changing state is impossible in these situations. That makes the tests a bit awkward.

3.2.4 onFulfilled/onRejected must be asynchronous?

Hi,

I would just like to ask if there is a specific reasoning behind this clause (specifically, notes 4.1) ensuring that onFulfilled/onRejected must occur in a separate tick from the call to then()?

I am currently writing a promises library in Java for the vert.x platform, and I'm being told that getting a static reference to vertx is not recommended and only for internal use only, which means my library would not conform to this spec without gratuitous use of reference passing.

Hopefully any answer you can give will enlighten me further.

Kind Regards,
Daryl

A way of synchronously retrieving fulfillment values and rejection reasons

This is a new idea that does not belong in the base spec; we are just using this issue tracker as a place for discussion.

Over in kriskowal/q#167, we're contemplating how to retrieve the value of a foreign fulfilled or rejected promise. The use case there is having an isPending(possiblyForeignPromise) predicate that doesn't give false positives, but I think the most compelling use case is speed for e.g. templating systems (to avoid DOM manipulation). I believe @ForbesLindesay has mentioned this being used in q-ejs, and I know @wycats had some interest in the issue as well. I've also heard second-hand that @lukehoban wasn't sure promises could be always-asynchronous because of such use cases.

This is largely a bikeshedding matter, but it'd be nice to have an interoperable standard. Currently Q uses the following semantics, which to be honest I'm not a huge fan of:

  • promise.valueOf() on a pending or rejected promise: returns promise.
  • promise.valueOf() on a fulfilled promise: returns the fulfillment value.
  • promise.valueOf().exception on a rejected promise: returns the rejection reason.

Other prior art:

  • RSVP uses resolvedValue and rejectedValue. Problems: uses the horribly-confusing term "resolve," and no way to distinguish between pending vs. fulfilled or rejected with undefined.
  • Mark Miller's concurrency strawman: promise.nearer() is like Q's promise.valueOf()
  • Can't find much more??

Stack traces

Stack traces with current Q are like super crappy and horrible. They only show part starting with setTimeout. Won’t it be great to have nice traces in promises.next? Or you think this should be left to folks who’ll implement the spec?

Authors and credit

Wanted to write it down so we don't forget :)

I think it's important to pass along tons of credit to @kriszyp and @kriskowal since this spec draws so heavily on Promises/A and UncommonJS Thenables. However, I think it's also important to give credit to the folks who have participated in the Promises/A+ discussions.

Need to write a credits section that captures both appropriately.

Done

Could we define the behaviour of the .done function? I really think all promises implementations should include this method, and it would be great if they were consistent.

I don't know if it belongs as part of this spec, or a separate spec, but I want to be able to say "The object has a .then method so it is a promise. The promise has a .done method, so .done will ensure errors are thrown."

Put promises-A+ logo on first line of all readmes

For everyone who makes either a promise library, or a promise consuming library:

I think it would be nice to have promises/A+ compliant libraries instantly identifiable in the readme. With that in mind, would people consider making:

<a href="http://promises-aplus.github.com/promises-spec"><img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png" align="right" /></a>

The first line of the readme for all their fully promises/A+ compatible libraries.

We need a LICENSE.txt

I'm partial to the WTFPL (see below), but I imagine MIT might be a bit more... conventional ;)

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
                    Version 2, December 2004

 Copyright (C) 2012 Domenic Denicola <[email protected]>

 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. You just DO WHAT THE FUCK YOU WANT TO.

Specify context in which callbacks are called

It's left unspecified what context (i.e. this value) onFulfilled and onRejected are called in. Should we specify? I say yes.

I think the obvious choice is undefined (which in sloppy mode becomes the global object), i.e. simply call the function as you normally would.

This prevents the antipattern of using this as a zeroth argument from creeping into implementations, which we currently allow and creates noninteroperable code.

Add self awareness of terminal promise to simulate done()?

Per Mariusz's point in esdiscuss, if the last promise in a chain throws, it will be swallowed by the promise, not propagated to the environment. http://old.nabble.com/Promises-to34648686.html#a34655893

It's possible for then() to register that a subsequent promise exists by flipping a flag inside then(). With this, it should be possible for a defaulted onRejected to relay if then() was called, or throw in a setImmediate() to propagate the error to the env for reporting if then() wasn't called. The error wouldn't be catchable, of course, but at least it would be visible. Also, being async, it wouldn't interrupt subsequent code.

Bad idea?

What to do if onFulfilled throws with no listeners attached to returned promise

If I have the following:

function SomeObj(){}
SomeObj.prototype.doSomething(){
  // does something
  // ...
  if(true && something.goes.wrong){
    throw new Error("I didn't expect to be running with promises");
  }
}

promiseSomething.then(function(result){
  var s = new SomeObj();
  s.doSomething(); // this error is swallowed
}, function(){
  // this obviously won't catch the error
})

This just happened to me. I get that the solution is to add a .then(null, function errhandler(){}), but it was definitely confusing.

Does the spec define what happens in this situation? This seems different than what was being discussed in #25.

Compliance branding (e.g. `then.aplus`)

From #1:

.then.aplus is actually ok with me. However, there's nothing to prevent someone from just slapping a truthy .aplus on their busted .then in a similar way that $.Deferred chose to use .then--i.e. without fully recognizing the implications. Maybe now that we have the Promises Test Suite, we can codify a Promises/A+ set of tests, and the community will have a way of ensuring that an implementation actually deserves .aplus?

However, I'm torn on whether we should require .aplus in order to consider something a promise at all. Maybe .then should signify a "promise-like thenable", and .aplus simply tightens that and allows you to make even more assumptions about the thing's behavior? Or maybe that's just asking for more pain and special casing? Thoughts?

Promises should provide light weight access to their values

With most promise implementations, apart from jquery, you only have one way to access the value of a promise (via then). In a lot of cases all the user really needs is the value, they don't need a new promise representing the value of whatever they do with the previous promises value. jquery gets by without even offering proper propagation semantics. I think this jquery style use of promises belongs in the spec since it offers efficiency (no need to create new promises all the time) and API improvements(chainability and semantics). It might also make it easier to interope with jquery style promises in the future since the two different styles of promise access will have their own names to go by.

I think this method should be called end and have the exact same API as then except return this instead of a new promise.

My recent implementation has some examples in its readme if you want to see what this style of promise chaining looks like. Its basically a hybrid of jquery and normal promises.

Does it belong in spec?

Assimilation

I would like a repository to discuss Assimilation. I have made the following draft to get the ball rolling:

Assimilation/A+ - Draft A

This spec aims to specify a method for converting a thenable into a promise in the users preferred form (for libraries). A good use case for this is that of the utility function timeout:

function timeout(promise, time) {
  return promise.assimilate({
    then: function (onFulfilled, onRejected) {
      promise.then(onFulfilled, onRejected);
      setTimeout(onRejected.bind(null, new Error('Operation Timed Out')), time);
    }
  })
}

It is not expected that all Promises/A+ promises will include this extension so if you want to support promise assimilation you should check for its support:

if (typeof promise.assimilate === 'function') {
  //use `assimilate` assuming it conforms to the contract below
}

Motivation

Simple utility functions like timeout should ideally be written once and be usable independently of the users personal preference for promise library. As such, utility functions like timeout need to return functions of the same type that they take in as arguments. The simplest method for doing this is to allow libraries to assimilate their own promises into the correct promise type.

Requirements: the assimilate method

A promise implementing this specification must have an assimilate method. The assimilate method must act as a function. i.e. the following are equivalent

//as a function
var assimilate = promise.assimilate;
assimilate(thenable);
//as a method
promise.assimilate(thenable);
  1. The assimilate method takes a single argument: thenableArg
  2. If thenableArg does not have a then method (i.e. thenableArg && typeof thenableArg.then === 'function' is false)
    1. It returns a promise (call it result)
    2. result is fulfilled with thenableArg
  3. If thenableArg has a then method (i.e. thenableArg && typeof thenableArg.then === 'function' is true)
    1. It returns a promise (call it result)
    2. It calls thenableArg.then providing two arguments, onFulfiled and onRejected
      1. If onFulfilled is called, result is fulfilled with the first argument of onFulfilled
      2. If onRejected is called, result is rejected with the first argument of onRejected
      3. It may optionally provide a third argument, onProgress, which should be used to fire progress handlers in a library specific way.
    3. thenableArg.then must not be called until the call to promise.assimilate has returned.

Notes

Optionally, if the thenableArg has other methods such as cancel these can be used as appropriate.

Remaining issues before "1.0"

I'd like to get a comprehensive read-through for nitpicks from at least @wycats and @kriskowal. For example @wycats mentioned that "onFulfilled and onRejected must not be called before then returns" is slightly confusing, and might be helped by at least a clarifying note saying how in practice it means handlers must be called asynchronously. And @kriskowal is very good at spec-language in general, and has experience in that space.

Similarly I'm not sure how I feel about the "General" and "Specific" headings/groupings, or the one-item "Recommendations" section.

I'd love to get Mark Miller's feedback as well, both as someone heavily involved in promises and as a TC-39 member.

As mentioned previously, I need to get the tests ready. I think once I do, there should be a link to them. And perhaps a note saying that you should pass all the tests to be considered compliant?

We should get a logo for this organization, and perhaps it'd be fun to create some "compliance badges" that RSVP, When, and Q could slap on their READMEs. Anybody know any designers? I'll reach out to a few.

We also need a GitHub repository description. A small 140-char-or-less tagline, if you will.

It seems I don't have editing access to the spec, so we should clarify what the roles are of this organization's members---are we advisory and @briancavalier is the gatekeeper of the spec? Similarly others are advisory and I'm the gatekeeper of the tests? Or is it more open than that?

Callback ordering

I had this issue come up recently while discussing tick conflation algorithms with when.js contributor @Twisol. Given this:

var p, f, g, h;
p = // let p be an already-fulfilled promise
f = g = h = function() {}; // Note: no additional asynchrony introduced

p.then(f).then(g);
p.then(h);

In what order should f, g, and h be called? Promises/A+ currently says that f must be called before h, and that f must be called before g. It doesn't say anything about the relationship between g and h, so currently, afaict, both sequences, fgh and fhg, are correct.

I quickly tested current implementations of when.js, avow, and Q, and all 3 do breadth-first: fhg.

Anyone have any thoughts on this? I'm not necessarily saying we should (or even could) specify anything, but more just opening up the discussion to see where it leads.

Create a "Differences from Promises/A" section or secondary document.

This might allow us to delete a sentence or two in the introduction, and helps highlight what the wins of this spec are. Here's what I remember so far:

  • No progress handler (leave it for future spec work).
  • No "interactive promise" stuff.
  • Cover the case of handlers returning a promise
  • Update/clarify terminology: "fulfilled", "rejected", "reason", and "pending" instead of vague words like "completion," "failure", "finished", "failed state".
  • Specify that the rejection reason passed to onRejected is the thrown error.
  • Require asynchronous resolution.
  • Specify ordering of callbacks for subsequent calls to then.
  • Do not require promise1 !== promise2.

This might be best put in a second document in the repository (differences-from-promises-a.md) which could allow us to expand on each item, and avoids crowding the main spec with stuff of mainly-historical interest.

Support for IndexedDB

This is an inquiry into whether it might be possible for Promises/A+ to support IndexedDB.

Naturally one answer might be, no, it's simply out of scope for Promises/A+.

On the other hand... it's looking like IndexedDB is going to be the major local store for web apps; the older Web SQL Database is deprecated (and never was implemented in Firefox), and it is impossible to use the venerable Web Storage safely from multiple windows (as Chrome doesn't implement the ill-specified storage mutex).

A promises interface to IndexedDB is much more pleasant than the native event model, so it would be nice to support it if we could.

The code below illustrates a scenario which uses four components. All components are written with the assumption that Promises/A+ is the only API available for promises (we don't use extensions such as otherwise and so on).

  • a base Promises library (e.g. when, avow, etc.)
  • a library which provides a promises based interface to IndexedDB.
  • an independent Promises utility library. Such a library provides useful utilities on top of promises (in this example it does tracing, something else it could do would be say an implementation similar to when.join, but built on top of Promises/A+ only). The utility library does not itself implement promises.
  • a user program which uses the IndexedDB library and the utility library.

In this example the code works when the synchronous when implementation is plugged in, but fails when the asynchronous avow library is plugged in. With IndexedDB, a transaction is only kept alive if it is referenced at least once through the event loop, and so calling callbacks in the next event loop causes the transaction to be lost.

Note that merely leaving unspecified whether callbacks are synchronous or asynchronous doesn't help. To be able to keep the transaction alive, the callback must be synchronous. Thus while the IndexedDB library would presumably decide to be synchronous, the user could not reliably combine the IndexedDB library with the independent utility library merely on the strength of the Promises/A+ spec (if the spec left the synchronous behavior unspecified).

Now this is entirely speculative, and I haven't written any code or thought it through, but suppose callbacks were by default required to be asynchronous, but (for a particular execution extent) callbacks could be required to be synchronous. A library would either generate a synchronous or asynchronous callback depending on the mode, or, if it could only support asynchronous callbacks (xhr requests etc.) it would throw an error if it were called in the wrong mode. The user could say however for a particular callback "no, this one can be asynchronous" (because it didn't use the transaction or whatever).

Well, probably too complicated to make it into Promises/A+, but interesting to think about anyway.

require ['avow', 'when'], (avow, _when) ->

  ## base Promises implementation

  pending = ->
    deferred = _when.defer()
    {
      promise: deferred.promise
      fulfill: deferred.resolve
      reject:  deferred.reject
    }

  # or

  # pending = ->
  #   v = avow()
  #   {
  #     promise: v.promise
  #     fulfill: v.fulfill
  #     reject: v.reject
  #   }


  ## a promises utility library

  fulfilled = (val) ->
    pend = pending()
    pend.fulfill(val)
    pend.promise

  isPromise = (x) -> x and typeof(x.then) is 'function'

  toPromise = (x) ->
    if isPromise(x)
      x
    else
      pend = pending()
      pend.fulfill(x)
      pend.promise

  trace = (name, promiseOrValue) ->
    promise = toPromise(promiseOrValue)
    promise.then((value) -> console.log 'trace', name, value)
    promise


  ## a Promises based wrapper library for indexDB

  indexedDB = window.indexedDB or
              window.mozIndexedDB or
              window.webkitIndexedDB

  request_to_promise = (req) ->
    pend = pending()
    req.onerror   = (event) -> pend.reject()
    req.onsuccess = (event) -> pend.fulfill(req.result)
    pend.promise

  delete_database = (database_name) ->
    request_to_promise(indexedDB.deleteDatabase(database_name))

  open_database = (database_name, version, onUpgradeNeeded) ->
    req = indexedDB.open(database_name, version)
    req.onupgradeneeded = (event) ->
      onUpgradeNeeded(event.target.result)
    request_to_promise req

  db_transaction = (db, store_names) ->
    fulfilled(db.transaction(store_names))

  store_get = (objectStore, key) ->
    request_to_promise objectStore.get(key)


  ## user code

  setup_database = (db) ->
    objectStore = db.createObjectStore("kv", { keyPath: "k" })
    objectStore.add({k: 'a', v: 1})
    objectStore.add({k: 'b', v: 2})

  delete_database('test')
  .then(=> open_database('test', 1, setup_database))
  .then((db) -> db_transaction(db, ['kv']))
  .then((tx) ->
     trace('transaction mode', tx.mode)
     .then(-> trace('a', store_get(tx.objectStore('kv'), 'a')))
     .then(-> trace('b', store_get(tx.objectStore('kv'), 'b')))
  )
  .then(null, (reason) =>
    console.log 'error', reason, reason.message
  )

Specify the absense of resolve/fulfill/reject methods

We should probably explicitly state somewhere that the promise object should only have methods to observe the promise, and not to mutate the state of the object. I know the spec aims to leave out how the promise is resolved, but we should probably still specify it happens elsewhere.
This might help reduce misunderstandings like #28

Multiple arguments to `onFulfilled` or `onRejected`?

For Resolvers/A+, is resolver.resolve(value1, value2, value3) passing to onFulfilled(value1, value2, value3) legal? It's functionally possible, but I'm not sure about existing implementation support? I'll forego the rest of my thoughts on it for now, but...

If that is feasible, then perhaps the promises spec should be less explicit about a promise's value being a single thing.

Linkable spec bullet points

As @Raynos mentioned over in the unhandled-rejections repo, it would be nice to link the spec bullet points. The ideal UI I think is the same as GitHub with their link icon, except for each bullet point instead of just for headings.

Has GitHub open-sourced, or has anyone cloned, their auto-linker script? Seems like we should just be able to drop a <script> tag into the gh-pages branch.

Terminology

Getting the terminology standardized would be really nice. Currently, the state of the art among Promises/A-compliant implementers is:

  • fulfilled: a promise state wherein a fulfillment value is available
  • rejected: a promise state wherein a rejection reason is available
  • resolved: a promise state encompassing both fulfilled and rejected
  • pending/unresolved: the initial promise state, when the promise is neither fulfilled nor rejected.

Furthermore, these implementers generally also include the following resolver-related verbs:

  • resolve(otherPromise): a verb, wherein the resolver tells its promise to take on the (possibly eventual) state of otherPromise.
  • reject(reason): a verb, wherein the resolver tells its promise to become rejected with reason.

As is, Promises/A+ switches from rejected to broken, and settles on "pending" while leaving any mention of "unresolved" or "resolved" out.

I kind of like this, as it allows us to separate the promise states {fulfilled, broken, pending} from the resolver verbs {resolve, reject}.

Compare this to the current status quo: the promise states are {fulfilled, rejected, unresolved} whereas the resolver verbs are {resolve, reject}. There is a great symmetry between reject and rejected, but that is deceptive, because resolve and resolved are almost entirely unrelated. (That is, you can resolve with an unresolved promise, which leaves the resolver's promise as "unresolved".) See also kriskowal/q#122 and the discussion contained therein.


Alternately, we could try to just standardize on the existing terminology, since there may not be much gain in changing. In that case we could leave attempting to fix the resolver/promise terminology mismatch to an eventual Resolvers/A+ spec.

Where to host this spec

In a similar "write it down so we don't forget," I think hosting the spec under a shared organization like "promises" or "promises-aplus" would be good. See e.g. amdjs

Clarify async requirement

From #11

For example @wycats mentioned that "onFulfilled and onRejected must not be called before then returns" is slightly confusing, and might be helped by at least a clarifying note saying how in practice it means handlers must be called asynchronously

Initial discussion

Initial discussion started in the original gist, but I decided to create a repo as I think it'll be easier for everyone to see history and diffs as this spec evolves, and to take advantage of the better discussion and commenting tools.

So, let's continue the discussion in this issue rather than the gist.

Maintain a list of conformant implementations

I think it'd be awesome to have a list of conformant implementations we can point to. Maybe with a one-sentence description of each by the authors. The requirement would be that they pass the test suite.

This would just be another doc in the repo, and could include details on how to put the logo in your README as per #57. Then we'd point people to the gh-pages version.

Right now I believe we have:

  • Q >= 0.8.12
  • rsvp >= 1.1
  • avow, unpublished version
  • when, unpublished version
  • then/promise >= 1.2.0
  • promeso >= 0.0.3
  • legendary >= 0.1.0
  • vow >= some early version, he passed the tests the moment they came out

Section titles should be numbered

While writing the tests, I noticed it would have been nice to be able to refer unambiguously to bullet points.

Ideally we could use CSS magic to get cool bullet names like 1.2.3.1, but that's stretching. Maybe on gh-pages?

Do we need to spec `valueOf`?

I wasn't really clear on exactly how that helped the Q/when.js assimilation story. Is it something we should spec here?

async requirement a blocker for iOS Safari?

In iOS Safari (such as on the iPad), inactive tabs (tabs other than the one that the user is currently looking at), can receive events such as xhr callbacks, storage events, postMessage, etc. However, while the tab is inactive, setTimeout and setInterval callbacks are not called. (On desktop browsers such as Chrome, setTimeout and setInterval may be throttled to one second in inactive tabs, but aren't completely disabled).

The async requirement ("In practical terms, an implementation must use a mechanism such as setTimeout....") would thus seem to threaten to make Promises/A+ unusable in the iOS Safari environment. Any tab may want to use promises for events that it may receive while it's inactive, but callbacks would fail to fire.

Even on the desktop actually using setTimeout (if nothing better is available) is problematic: the throttling behavior would be that callbacks would be delayed by a minimum of 1,000 milliseconds...

Should promises be allowed as values?

Q 0.9 allows fulfilling with a promise, via deferred.fulfill(promise) (as opposed to deferred.resolve). @kriskowal can speak more on why this is necessary (for remote promises I believe), but just intuitively, it seems OK.

I think we should allow values to be promises. The only thing this impacts, apart from the Terminology section, is the chaining clause:

"If either onFulfilled or onRejected returns a value value that is not a promise"

Regarding footnote #2 (promise.then() === promise)

Should this really be left undefined? It has implications of how third-party libraries may interact. Assume in the code below that we try to be as cheap as possible and return a reference instead of a copy of the promise whenever possible:

// third-party library #1
function doStuff() {
  var promise = ...;
  return promise;
}

// third-party library #2
function doOtherStuff() {
  // this library augments the doStuff call and returns the result of .then(...)
  var promise = doStuff().then(...);
  return promise;
}

// my app code
var promise = doOtherStuff();
promise.then(...);
// additional fail condition in my app fails my reference to promise
if (...) promise.reject();

What will happen above is that "third-party library #2" will think "third-party library #1" failed (but its promise was actually rejected in "my app"), an incorrect assumption. This can lead to the libraries having side-effects that should only ever happen if there was an actual error.

To work around the above problem, the "my app" developer would in this case have to create their own promise and have it resolve or reject whenever the original promise does, in addition to the local fail conditions. This means complicating the app more than is needed. Always returning a copy would never have this problem of disturbing states of promises across application realms.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.