@@ -295,6 +295,12 @@ public Promise(Action<Action<PromisedT>, Action<Exception>> resolver)
295295 }
296296 }
297297
298+ private Promise ( PromiseState initialState )
299+ {
300+ CurState = initialState ;
301+ id = Promise . NextId ( ) ;
302+ }
303+
298304 /// <summary>
299305 /// Add a rejection handler for this promise.
300306 /// </summary>
@@ -378,7 +384,8 @@ private void InvokeRejectHandlers(Exception ex)
378384
379385 if ( rejectHandlers != null )
380386 {
381- rejectHandlers . Each ( handler => InvokeHandler ( handler . callback , handler . rejectable , ex ) ) ;
387+ for ( int i = 0 , maxI = rejectHandlers . Count ; i < maxI ; ++ i )
388+ InvokeHandler ( rejectHandlers [ i ] . callback , rejectHandlers [ i ] . rejectable , ex ) ;
382389 }
383390
384391 ClearHandlers ( ) ;
@@ -406,7 +413,8 @@ private void InvokeProgressHandlers(float progress)
406413 {
407414 if ( progressHandlers != null )
408415 {
409- progressHandlers . Each ( handler => InvokeHandler ( handler . callback , handler . rejectable , progress ) ) ;
416+ for ( int i = 0 , maxI = progressHandlers . Count ; i < maxI ; ++ i )
417+ InvokeHandler ( progressHandlers [ i ] . callback , progressHandlers [ i ] . rejectable , progress ) ;
410418 }
411419 }
412420
@@ -510,6 +518,9 @@ public void Done(Action<PromisedT> onResolved)
510518 /// </summary>
511519 public void Done ( )
512520 {
521+ if ( CurState == PromiseState . Resolved )
522+ return ;
523+
513524 Catch ( ex =>
514525 Promise . PropagateUnhandledException ( this , ex )
515526 ) ;
@@ -529,6 +540,11 @@ public IPromise<PromisedT> WithName(string name)
529540 /// </summary>
530541 public IPromise Catch ( Action < Exception > onRejected )
531542 {
543+ if ( CurState == PromiseState . Resolved )
544+ {
545+ return Promise . Resolved ( ) ;
546+ }
547+
532548 var resultPromise = new Promise ( ) ;
533549 resultPromise . WithName ( Name ) ;
534550
@@ -558,6 +574,11 @@ public IPromise Catch(Action<Exception> onRejected)
558574 /// </summary>
559575 public IPromise < PromisedT > Catch ( Func < Exception , PromisedT > onRejected )
560576 {
577+ if ( CurState == PromiseState . Resolved )
578+ {
579+ return this ;
580+ }
581+
561582 var resultPromise = new Promise < PromisedT > ( ) ;
562583 resultPromise . WithName ( Name ) ;
563584
@@ -645,9 +666,21 @@ public IPromise<ConvertedT> Then<ConvertedT>(
645666 Action < float > onProgress
646667 )
647668 {
669+ if ( CurState == PromiseState . Resolved )
670+ {
671+ try
672+ {
673+ return onResolved ( resolveValue ) ;
674+ }
675+ catch ( Exception ex )
676+ {
677+ return Promise < ConvertedT > . Rejected ( ex ) ;
678+ }
679+ }
680+
648681 // This version of the function must supply an onResolved.
649682 // Otherwise there is now way to get the converted value to pass to the resulting promise.
650- // Argument.NotNull(() => onResolved);
683+ // Argument.NotNull(() => onResolved);
651684
652685 var resultPromise = new Promise < ConvertedT > ( ) ;
653686 resultPromise . WithName ( Name ) ;
@@ -700,6 +733,18 @@ Action<float> onProgress
700733 /// </summary>
701734 public IPromise Then ( Func < PromisedT , IPromise > onResolved , Action < Exception > onRejected , Action < float > onProgress )
702735 {
736+ if ( CurState == PromiseState . Resolved )
737+ {
738+ try
739+ {
740+ return onResolved ( resolveValue ) ;
741+ }
742+ catch ( Exception ex )
743+ {
744+ return Promise . Rejected ( ex ) ;
745+ }
746+ }
747+
703748 var resultPromise = new Promise ( ) ;
704749 resultPromise . WithName ( Name ) ;
705750
@@ -720,15 +765,19 @@ public IPromise Then(Func<PromisedT, IPromise> onResolved, Action<Exception> onR
720765 }
721766 } ;
722767
723- Action < Exception > rejectHandler = ex =>
768+ Action < Exception > rejectHandler ;
769+ if ( onRejected != null )
724770 {
725- if ( onRejected != null )
771+ rejectHandler = ex =>
726772 {
727773 onRejected ( ex ) ;
728- }
729-
730- resultPromise . Reject ( ex ) ;
731- } ;
774+ resultPromise . Reject ( ex ) ;
775+ } ;
776+ }
777+ else
778+ {
779+ rejectHandler = resultPromise . Reject ;
780+ }
732781
733782 ActionHandlers ( resultPromise , resolveHandler , rejectHandler ) ;
734783 if ( onProgress != null )
@@ -744,6 +793,19 @@ public IPromise Then(Func<PromisedT, IPromise> onResolved, Action<Exception> onR
744793 /// </summary>
745794 public IPromise Then ( Action < PromisedT > onResolved , Action < Exception > onRejected , Action < float > onProgress )
746795 {
796+ if ( CurState == PromiseState . Resolved )
797+ {
798+ try
799+ {
800+ onResolved ( resolveValue ) ;
801+ return Promise . Resolved ( ) ;
802+ }
803+ catch ( Exception ex )
804+ {
805+ return Promise . Rejected ( ex ) ;
806+ }
807+ }
808+
747809 var resultPromise = new Promise ( ) ;
748810 resultPromise . WithName ( Name ) ;
749811
@@ -757,15 +819,19 @@ public IPromise Then(Action<PromisedT> onResolved, Action<Exception> onRejected,
757819 resultPromise . Resolve ( ) ;
758820 } ;
759821
760- Action < Exception > rejectHandler = ex =>
822+ Action < Exception > rejectHandler ;
823+ if ( onRejected != null )
761824 {
762- if ( onRejected != null )
825+ rejectHandler = ex =>
763826 {
764827 onRejected ( ex ) ;
765- }
766-
767- resultPromise . Reject ( ex ) ;
768- } ;
828+ resultPromise . Reject ( ex ) ;
829+ } ;
830+ }
831+ else
832+ {
833+ rejectHandler = resultPromise . Reject ;
834+ }
769835
770836 ActionHandlers ( resultPromise , resolveHandler , rejectHandler ) ;
771837 if ( onProgress != null )
@@ -817,6 +883,64 @@ private void ProgressHandlers(IRejectable resultPromise, Action<float> progressH
817883 }
818884 }
819885
886+ /// <summary>
887+ /// Chain a number of operations using promises.
888+ /// Returns the value of the first promise that resolves, or otherwise the exception thrown by the last operation.
889+ /// </summary>
890+ public static IPromise < T > First < T > ( params Func < IPromise < T > > [ ] fns )
891+ {
892+ return First ( ( IEnumerable < Func < IPromise < T > > > ) fns ) ;
893+ }
894+
895+ /// <summary>
896+ /// Chain a number of operations using promises.
897+ /// Returns the value of the first promise that resolves, or otherwise the exception thrown by the last operation.
898+ /// </summary>
899+ public static IPromise < T > First < T > ( IEnumerable < Func < IPromise < T > > > fns )
900+ {
901+ var promise = new Promise < T > ( ) ;
902+
903+ int count = 0 ;
904+
905+ fns . Aggregate (
906+ Promise < T > . Rejected ( null ) ,
907+ ( prevPromise , fn ) =>
908+ {
909+ int itemSequence = count ;
910+ ++ count ;
911+
912+ var newPromise = new Promise < T > ( ) ;
913+ prevPromise
914+ . Progress ( v =>
915+ {
916+ var sliceLength = 1f / count ;
917+ promise . ReportProgress ( sliceLength * ( v + itemSequence ) ) ;
918+ } )
919+ . Then ( ( Action < T > ) newPromise . Resolve )
920+ . Catch ( ex =>
921+ {
922+ var sliceLength = 1f / count ;
923+ promise . ReportProgress ( sliceLength * itemSequence ) ;
924+
925+ fn ( )
926+ . Then ( value => newPromise . Resolve ( value ) )
927+ . Catch ( newPromise . Reject )
928+ . Done ( )
929+ ;
930+ } )
931+ ;
932+ return newPromise ;
933+ } )
934+ . Then ( value => promise . Resolve ( value ) )
935+ . Catch ( ex =>
936+ {
937+ promise . ReportProgress ( 1f ) ;
938+ promise . Reject ( ex ) ;
939+ } ) ;
940+
941+ return promise ;
942+ }
943+
820944 /// <summary>
821945 /// Chain an enumerable of promises, all of which must resolve.
822946 /// Returns a promise for a collection of the resolved results.
@@ -989,8 +1113,8 @@ public static IPromise<PromisedT> Race(IEnumerable<IPromise<PromisedT>> promises
9891113 /// </summary>
9901114 public static IPromise < PromisedT > Resolved ( PromisedT promisedValue )
9911115 {
992- var promise = new Promise < PromisedT > ( ) ;
993- promise . Resolve ( promisedValue ) ;
1116+ var promise = new Promise < PromisedT > ( PromiseState . Resolved ) ;
1117+ promise . resolveValue = promisedValue ;
9941118 return promise ;
9951119 }
9961120
@@ -1001,17 +1125,30 @@ public static IPromise<PromisedT> Rejected(Exception ex)
10011125 {
10021126// Argument.NotNull(() => ex);
10031127
1004- var promise = new Promise < PromisedT > ( ) ;
1005- promise . Reject ( ex ) ;
1128+ var promise = new Promise < PromisedT > ( PromiseState . Rejected ) ;
1129+ promise . rejectionException = ex ;
10061130 return promise ;
10071131 }
10081132
10091133 public IPromise < PromisedT > Finally ( Action onComplete )
10101134 {
1135+ if ( CurState == PromiseState . Resolved )
1136+ {
1137+ try
1138+ {
1139+ onComplete ( ) ;
1140+ return this ;
1141+ }
1142+ catch ( Exception ex )
1143+ {
1144+ return Rejected ( ex ) ;
1145+ }
1146+ }
1147+
10111148 var promise = new Promise < PromisedT > ( ) ;
10121149 promise . WithName ( Name ) ;
10131150
1014- this . Then ( x => promise . Resolve ( x ) ) ;
1151+ this . Then ( ( Action < PromisedT > ) promise . Resolve ) ;
10151152 this . Catch ( e => {
10161153 try {
10171154 onComplete ( ) ;
@@ -1052,7 +1189,7 @@ public IPromise<ConvertedT> ContinueWith<ConvertedT>(Func<IPromise<ConvertedT>>
10521189
10531190 public IPromise < PromisedT > Progress ( Action < float > onProgress )
10541191 {
1055- if ( onProgress != null )
1192+ if ( CurState == PromiseState . Pending && onProgress != null )
10561193 {
10571194 ProgressHandlers ( this , onProgress ) ;
10581195 }
0 commit comments