Closed domenic closed 11 years ago
This strawman is based on a few guiding ideas:
return
in the Promises/A+ spec, is useful: thus resolver
's function behavior.throw
in promises-aplus/promises-spec#66, is not useful. It's specified to prevent promises-for-promises, but is not something people want available to use.resolver.fulfill(value)
fulfills the promise with value
resolver.reject(reason)
rejects the promise with reason
resolver.yield(otherPromise)
yields the promise to otherPromise
factory
returning a value or throwing an exception.instanceof
and constructor-discovery, and provides a strong idiomatic way of creating new objects---including promises.resolver.fulfill
throws an AlreadySettledError
.I don't like Notes-1:
Consider this function:
function doAsyncWork() {
return new Promise(function (resolver) {
var resA = doSynchronousPreparationWhichMightThrowAnException();
resolver.resolve(doAsyncWork(resA));
});
}
If you want to call it and be sure of handling all errors you need code to handle both synchronous and asynchronous errors, this is really bad.
Otherwise this is mostly fine. I'd be inclined to cut yield
entirely. Especially given it's potential confusion with the ES6 yield
keyword.
I strongly oppose points 3 and 4. This would prevent any inheritance approaches (and this constructor proposal is all about inheritance, isn't it?). While I really like instanceof
, settling the [[prototype]] makes it unnecessary limited.
For example, in my https://github.com/bergus/F/blob/master/Promise.js I have implemented a Stream
to be a "subclass" of Promise
(basically with chunked fulfillments).
My proposal would be to omit point 3 (2 should be enough), and change 4 to:
promise.constructor
must be a function with all the properties of a Promise constructor (1-6), yet it must not necessarily === Promise
.PS: Didn't we forget something substantial (point 0 or so):
promise
must implement the Promise/A+ specI think points 3 and 4 only refer to a promise created from var promise = new Promise(fn)
.
OK, that's good (though it excludes implementations that want to return subclass instances from the Promise
constructor, maybe dependent on optional further arguments). However I fear it could confuse people (just as it confused me) and make them to (ab-)using these properties for type checking (especially the constructor
thing).
Still they don't seem really necessary to me, it would be nice to add at least some reasoning. Also, point 3 should be fixed to
Object.getPrototypeOf(promise) === Promise.prototye // encloses Point 2, btw
Promise
can be substituted for whatever library name you want to give it in this spec, so you would just need to ensure chunkifiedPromise.constructor === ChunkifiedPromise.prototype.constructor === ChunkifiedPromise
etc.
Killing this in favor of #18, mainly because it contains terminology and behavior confusion around "resolved" and "settled". If someone wants something more like this, with argument-type checking, but with #18's not-confused resolution process, we can create a new draft.
Terminology
The Promise Constructor
new
, with the same results.promise instanceof Promise
must be true.Object.getPrototypeOf(promise) === Promise.prototype
must be true.promise.constructor === Promise.prototype.constructor === Promise
must be true.factory
is not a function, the implementation must throw aTypeError
.factory
is a function, it must be called immediately (i.e. within the same turn of the event loop), with a resolver. (note 1)The Resolver
The resolver is a function with several properties, which are also functions.
this
value.resolver(x)
x
is a non-promise,promise
is pending,promise
must be fulfilled withx
as its fulfillment value.promise
is settled, nothing happens (in particular, no exception may be thrown).x
is a promise,promise
must assume the state ofx
(see Promises/A+ spec).resolver.fulfill(value)
value
is a non-promise,promise
is pending,promise
must be fulfilled withvalue
as its fulfillment value.promise
is settled, nothing happens (in particular, no exception may be thrown).value
is a promise, the implementation must throw aTypeError
.resolver.reject(reason)
reason
is a non-promise,promise
is pending,promise
must be rejected withreason
as its rejection reason.promise
is settled, nothing happens (in particular, no exception may be thrown).reason
is a non-promise, the implementation must throw aTypeError
.resolver.yield(otherPromise) [normative optional? cut entirely?]
otherPromise
is a promise,promise
is pending,promise
must assume the state ofotherPromise
(see Promises/A+ spec).promise
is settled, nothing happens (in particular, no exception may be thrown).otherPromise
is not a promise, the implementation must throw aTypeError
.Notes
factory
throws an exception, since it is called within the same turn of the event loop asnew Promise
,promise
will never be successfully created and the error will be uncaught by the implementation. [is this note even necessary?]