[squeak-dev] The Inbox: Kernel-tonyg.1148.mcz
Marcel Taeumel
marcel.taeumel at hpi.de
Fri Feb 2 06:44:53 UTC 2018
+1 for #isPromise
I don't think we need the #isKindOf: "flavor" here because the basic concept seems to be quite mature and thus justifies the addition to the Object protocol.
(For other discussions about #isKindOf: see the history of the mailing list. There was at least one in combination with Morphic Flaps.)
Best,
Marcel
Am 01.02.2018 01:34:33 schrieb Eliot Miranda <eliot.miranda at gmail.com>:
Hi Tony,
On Wed, Jan 31, 2018 at 3:37 PM, <commits at source.squeak.org [mailto:commits at source.squeak.org]> wrote:
A new version of Kernel was added to project The Inbox:
http://source.squeak.org/inbox/Kernel-tonyg.1148.mcz [http://source.squeak.org/inbox/Kernel-tonyg.1148.mcz]
==================== Summary ====================
Name: Kernel-tonyg.1148
Author: tonyg
Time: 31 January 2018, 11:37:21.27021 pm
UUID: 2a675301-406b-4222-9599-84358a7cc506
Ancestors: Kernel-eem.1147
Brings the Promise implementation closer to Javascript/A+ promises in two ways:
* Resolving a Promise with another Promise causes them to be chained together
* Resolving or Rejecting a Promise that is not pending is a no-op, like the Firefox/Chrome/etc in-browser promise implementations.
The tests have been changed in KernelTests-tonyg.331 accordingly.
=============== Diff against Kernel-eem.1147 ===============
Item was changed:
Object subclass: #Promise
+ instanceVariableNames: 'value resolvers mutex state error rejecters'
- instanceVariableNames: 'onError value resolvers mutex state error rejectors rejecters'
classVariableNames: ''
poolDictionaries: ''
category: 'Kernel-Processes'!
+ !Promise commentStamp: 'tonyg 1/31/2018 23:34' prior: 0!
- !Promise commentStamp: 'fbs 5/17/2013 18:23' prior: 0!
I represent the result of an asynchronous message. Once the message is processed, I will be resolved to a value. I am typically instantiated by invocations of #futureSend:at:args: (and not by #futureDo:atArgs:).
See class-comment of FutureNode.
I also implement the Promises/A+ Javascript specification. This allows you to chain my instances to perform arbitrarily complex asynchronous tasks with error handling baked in.
+ A Promise may be in one of three possible states: #pending, #fulfilled or #rejected. A Promise may move from #pending -> #fulfilled (by way of the resolveWith: message), or from #pending -> #rejected (by way of rejectWith:). No other state changes may occur.
+
+ Once #fulfilled or #rejected, a Promise's value must not change. In keeping with the major Javascript Promise implementations' interpretations of this, calls to resolveWith: or rejectWith: when a Promise is in #fulfilled or #rejected state are simply ignored - an error is not signalled. (See test cases PromiseTest testFirstResolutionWins, testCannotRejectFulfilledPromise and testCannotResolveaRejectedPromise.)!
- A Promise may be in one of three possible states: #pending, #fulfilled or #rejected. A Promise may move from #pending -> #fulfilled, or from #pending -> #rejected. No other state changes may occur. Once #fulfilled or #rejected, a Promise's value must change.!
Item was changed:
----- Method: Promise>>rejectWith: (in category 'resolving') -----
rejectWith: anObject
"Reject this promise."
mutex critical: [
+ (state == #pending) ifTrue: [
+ error := anObject.
+ state := #rejected.
+ rejecters do: [:r | self evaluateRejecter: r]]]!
- (state == #fulfilled) ifTrue: [self error: 'Promise was already resolved'].
- (state == #rejected) ifTrue: [self error: 'Promise was already rejected'].
- error := anObject.
- state := #rejected.
- rejecters do: [:r | self evaluateRejecter: r]].!
Item was changed:
----- Method: Promise>>resolveWith: (in category 'resolving') -----
resolveWith: arg
+ "Resolve this promise. If arg is itself a Promise, make this promise depend upon it,
+ as detailed in the Promises/A+ spec:
+ https://promisesaplus.com/#the-promise-resolution-procedure [https://promisesaplus.com/#the-promise-resolution-procedure]"
+
+ (arg isKindOf: Promise)
I'd /much/ rather see Object>>isPromise and Promise>>isPromise than this.
+ ifTrue: [
+ arg whenResolved: [:v | self resolveWith: v].
+ arg whenRejected: [:e | self rejectWith: e]]
+ ifFalse: [
+ mutex critical: [
+ (state == #pending) ifTrue: [
+ value := arg.
+ state := #fulfilled.
+ resolvers do: [:r | self evaluateResolver: r]]]]!
- "Resolve this promise"
- mutex critical: [
- (state == #fulfilled) ifTrue: [self error: 'Promise was already resolved'].
- (state == #rejected) ifTrue: [self error: 'Promise was already resolved'].
- value := arg.
- state := #fulfilled.
- resolvers do: [:r |
- self evaluateResolver: r]].!
Item was changed:
----- Method: Promise>>then: (in category 'monad') -----
then: resolvedBlock
+ ^ self then: resolvedBlock ifRejected: [:e | "Pass rejection reason along" e].!
- ^ self then: resolvedBlock ifRejected: [:ignored | "Do nothing"].!
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20180202/52742ea1/attachment.html>
More information about the Squeak-dev
mailing list
|