-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Comparing ES Harmony Concurrency Strawman
Mark Miller and Kris Kowal (yours truly) are frequently experimenting and converging around Mark’s Concurrency Strawman for a future version of the ECMAScript specification. This is an analysis of the present (March 2012) differences between Q and the standard proposal.
-
Resolve: Q does not support the proposed
Q()function. The proposed behavior is equivalent to the presentQ.resolve()as proposed by @domenic and the legacy (still supported)Q.ref()as implemented in the original Waterkenref_sendon which Q is based. ThisQimplementation providescallandapplymethods for sending messages to promised functions. These would conflict withcallandapplyon theFunction.prototype. -
Reject: The
Q.reject(error)function is implemented as proposed. I may eventually restrict the domain of the error to exception objects, or at least restrict strings, so that I can make some stronger guarantees to error handlers. -
isPromise: The
Q.isPromisefunction is implemented as specified, as well asQ.isFulfilled(which tolerates non-promise values),Q.isRejected,Q.isResolvedas well as these functions as promise methods except **promise.isPromise(). -
When/Then: Q does support
promise.when()in the interest of compatibility with this specification, but thepromise.then()interface has won over the JavaScript community. Q promises’thenmethod supports the CommonJS/A specification as proposed by Kris Zyp.Q.resolve(promise)is also able to “assimilate” other objects that havethenmethods as long as they are designed to call the givenfulfilledorrejectedfunctions; a property supported by Dojo promises and even the errant jQuery promises.Q.resolve(promise)ignores the return-value of thethen, ensuring that the assimilated promise is in-fact aQpromise with all of the provided methods and behaviors. I recall that a colleague of Mark Miller found a reason why the method should be namedwheninstead ofthen, but I do not recall the argument and it has not surfaced a problem in my practice.The
endfunction is implemented as specified, and also implemented asQ.end(promise).In addition, this implementation provides some shorthands:
promise.fail(errback)andpromise.fin(finback).The
failfunction is a shorthand for passing only an errback tothen. I may add support for a default noop errback. Presently, not providing an errback is the same as providing neither an errback nor a callback, which just forwards the resolution of the previous promise: which is to say it is an utterly useless pattern.
The ``finback`` receives no arguments, its fulfillment value is ignored — the resolution of the promise gets forwarded. However, if the finback returns a promise, the resolution of that promise may delay the forwarding. If the finback returns a promise that is eventually rejected, or if it throws an exception, the new error overrides the original resolution.
-
Get/Put/Post: The
get,put, andpostare all implemented as proposed. The proposeddeleteis calleddelinQ, but experimentally aliased asdelete.
The proposed ``promise.send`` is equivalent to the implemented ``promise.invoke``. I have reserved ``promise.send`` for sending messages to promises, but I have not documented it and the signature may be some combination of ``operator``, ``resolve``, and variadic arguments, where operators are like ``"get"`` and ``"del"``. I may change the ``"when"`` operator to ``"then"`` and ``"del"`` to ``"delete"``. I think there is some flexibility here still since it is only substantial to the protocol spoken between the Q and Q-Comm libraries. My operator names differ from Tyler Close’s original Waterken ref_send in that they are all lower-case.
-
Nearer Value: The proposed
Q.nearer(promise)is almost equivalent to the implementedpromise.valueOf(). If the promise is fulfilled,promise.valueOf()returns the fulfilled value. If the promise is or has forwarded to a deferred promise, it returns most recently deferred promise (the specification says that it should return the original promise, but I presume this is not intentional). For rejected promises,promise.valueOf()returns a sentinel object with{rejectedPromise: true, reason: {}}; I intend to alter the implementation to meet the specification in this regard. -
All: The proposed
Q.all(...args)is implemented as non-variadicQ.all(args). In the absence of rest arguments, we recover the cost of adding brackets in some places in not having to wrap promises likeQ.all.apply(null, promises)in other cases. I’ve recently addedQ.allResolved(promises)andpromiseForPromises.allResolved(). -
Delay: I implemented
Q.delayslightly differently. The proposal isQ.delay(millis, answer). To be consistent with other methods implemented both on theQobject and on the promise object, this implementation puts the “answer” first, so the argument forms are:Q.delay(answer, millis),promise.delay(millis). For convenience, I recognize that when only one argument is provided (as indicated byarguments.length), the answer is undefined,Q.delay(millies).then(function () {}). -
Async: I have implemented
Q.asyncas proposed, including support forReturnValueerrors as proposed for Harmony but not yet implemented in FireFox’s SpiderMonkey. -
Remotes and Vats: I have not implemented
makeFar,makeRemote,race, orjoinin this library. I have left these to the purview of Q-Comm. I would like to implement vats andwhere(orthereto be consistent withthen) in WebWorkers and Node subprocesses uses ES5-Lab’s SES initializer. -
Others:* I also have not implemented
memoizein this library since I do not want to entrain aWeakMapshim.
I have also begun experimenting with the following keyword aliases:
-
finallyforfin -
catchforfail(when(promise, void 0, callback)) -
tryforcall(e.g.,Q.try(f).catch(f).finally(f).end())