From be1243ea3f1eb28c5f267e2cdd4ef8080fa3af5c Mon Sep 17 00:00:00 2001 From: Nathan Loewen Date: Fri, 17 Mar 2017 13:27:15 -0500 Subject: [PATCH 1/2] Create base class for promises This allows code which can handle any type of promise. Creating IPromiseBase allows IPromise, IPromise, and IPromise to all be treated identically, without creating code branches for each. The IPromiseBase interface is implemented explicitly, which avoids creating ambiguous functions. Additionally, the Promise_Base class allows for a decent amount of code reuse between generic and non-generic promises. --- C-Sharp-Promise.csproj | 1 + Promise.cs | 236 +++++++++++---------------------- Promise_Base.cs | 287 +++++++++++++++++++++++++++++++++++++++++ Promise_NonGeneric.cs | 266 ++++++++++++-------------------------- 4 files changed, 445 insertions(+), 345 deletions(-) create mode 100644 Promise_Base.cs diff --git a/C-Sharp-Promise.csproj b/C-Sharp-Promise.csproj index e3d6bf2..e85ea47 100644 --- a/C-Sharp-Promise.csproj +++ b/C-Sharp-Promise.csproj @@ -46,6 +46,7 @@ + diff --git a/Promise.cs b/Promise.cs index e3ca483..bfecaf8 100644 --- a/Promise.cs +++ b/Promise.cs @@ -10,41 +10,31 @@ namespace RSG /// Implements a C# promise. /// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise /// - public interface IPromise + public interface IPromise : IPromiseBase { - /// - /// Gets the id of the promise, useful for referencing the promise during runtime. - /// - int Id { get; } - /// /// Set the name of the promise, useful for debugging. /// - IPromise WithName(string name); + new IPromise WithName(string name); /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// onRejected is called on error. /// void Done(Action onResolved, Action onRejected); /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// Adds a default error handler. /// void Done(Action onResolved); /// - /// Complete the promise. Adds a default error handler. + /// Handle errors for the promise. /// - void Done(); - - /// - /// Handle errors for the promise. - /// - IPromise Catch(Action onRejected); + new IPromise Catch(Action onRejected); /// /// Add a resolved callback that chains a value promise (optionally converting to a different value type). @@ -123,17 +113,6 @@ public interface IPromise IPromise ThenRace(Func> chain); } - /// - /// Interface for a promise that can be rejected. - /// - public interface IRejectable - { - /// - /// Reject the promise with an exception. - /// - void Reject(Exception ex); - } - /// /// Interface for a promise that can be rejected or resolved. /// @@ -150,79 +129,28 @@ public interface IPendingPromise : IRejectable void Resolve(PromisedT value); } - /// - /// Specifies the state of a promise. - /// - public enum PromiseState - { - Pending, // The promise is in-flight. - Rejected, // The promise has been rejected. - Resolved // The promise has been resolved. - }; - /// /// Implements a C# promise. /// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise /// - public class Promise : IPromise, IPendingPromise, IPromiseInfo + public class Promise : Promise_Base, IPromise, IPendingPromise { - /// - /// The exception when the promise is rejected. - /// - private Exception rejectionException; - /// /// The value when the promises is resolved. /// private PromisedT resolveValue; - /// - /// Error handler. - /// - private List rejectHandlers; - /// /// Completed handlers that accept a value. /// private List> resolveCallbacks; private List resolveRejectables; - /// - /// ID of the promise, useful for debugging. - /// - public int Id { get; } - - /// - /// Name of the promise, when set, useful for debugging. - /// - public string Name { get; private set; } - - /// - /// Tracks the current state of the promise. - /// - public PromiseState CurState { get; private set; } - - public Promise() - { - this.CurState = PromiseState.Pending; - this.Id = Promise.NextId(); + public Promise() : base() + { } - if (Promise.EnablePromiseTracking) - { - Promise.pendingPromises.Add(this); - } - } - - public Promise(Action, Action> resolver) + public Promise(Action, Action> resolver) : this() { - this.CurState = PromiseState.Pending; - this.Id = Promise.NextId(); - - if (Promise.EnablePromiseTracking) - { - Promise.pendingPromises.Add(this); - } - try { resolver( @@ -239,19 +167,6 @@ public Promise(Action, Action> resolver) } } - /// - /// Add a rejection handler for this promise. - /// - private void AddRejectHandler(Action onRejected, IRejectable rejectable) - { - if (rejectHandlers == null) - { - rejectHandlers = new List(); - } - - rejectHandlers.Add(new RejectHandler() { callback = onRejected, rejectable = rejectable }); ; - } - /// /// Add a resolve handler for this promise. /// @@ -271,49 +186,16 @@ private void AddResolveHandler(Action onResolved, IRejectable rejecta resolveRejectables.Add(rejectable); } - /// - /// Invoke a single handler. - /// - private void InvokeHandler(Action callback, IRejectable rejectable, T value) - { -// Argument.NotNull(() => callback); -// Argument.NotNull(() => rejectable); - - try - { - callback(value); - } - catch (Exception ex) - { - rejectable.Reject(ex); - } - } - /// /// Helper function clear out all handlers after resolution or rejection. /// - private void ClearHandlers() + protected override void ClearHandlers() { - rejectHandlers = null; + base.ClearHandlers(); resolveCallbacks = null; resolveRejectables = null; } - /// - /// Invoke all reject handlers. - /// - private void InvokeRejectHandlers(Exception ex) - { -// Argument.NotNull(() => ex); - - if (rejectHandlers != null) - { - rejectHandlers.Each(handler => InvokeHandler(handler.callback, handler.rejectable, ex)); - } - - ClearHandlers(); - } - /// /// Invoke all resolve handlers. /// @@ -329,29 +211,6 @@ private void InvokeResolveHandlers(PromisedT value) ClearHandlers(); } - /// - /// Reject the promise with an exception. - /// - public void Reject(Exception ex) - { -// Argument.NotNull(() => ex); - - if (CurState != PromiseState.Pending) - { - throw new ApplicationException("Attempt to reject a promise that is already in state: " + CurState + ", a promise can only be rejected when it is still in state: " + PromiseState.Pending); - } - - rejectionException = ex; - CurState = PromiseState.Rejected; - - if (Promise.EnablePromiseTracking) - { - Promise.pendingPromises.Remove(this); - } - - InvokeRejectHandlers(ex); - } - /// /// Resolve the promise with a particular value. /// @@ -374,7 +233,7 @@ public void Resolve(PromisedT value) } /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// onRejected is called on error. /// @@ -387,7 +246,7 @@ public void Done(Action onResolved, Action onRejected) } /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// Adds a default error handler. /// @@ -399,6 +258,32 @@ public void Done(Action onResolved) ); } + /// + /// Completes the promise. + /// onResolved is called on successful completion. + /// onRejected is called on error. + /// + void IPromiseBase.Done(Action onResolved, Action onRejected) + { + Then((x) => { onResolved(new PromiseResult(x)); }, onRejected) + .Catch(ex => + Promise.PropagateUnhandledException(this, ex) + ); + } + + /// + /// Completes the promise. + /// onResolved is called on successful completion. + /// Adds a default error handler. + /// + void IPromiseBase.Done(Action onResolved) + { + Then((x) => { onResolved(new PromiseResult(x)); }) + .Catch(ex => + Promise.PropagateUnhandledException(this, ex) + ); + } + /// /// Complete the promise. Adds a default error handler. /// @@ -418,8 +303,13 @@ public IPromise WithName(string name) return this; } + IPromiseBase IPromiseBase.WithName(string name) + { + return WithName(name); + } + /// - /// Handle errors for the promise. + /// Handle errors for the promise. /// public IPromise Catch(Action onRejected) { @@ -445,6 +335,11 @@ public IPromise Catch(Action onRejected) return resultPromise; } + IPromiseBase IPromiseBase.Catch(Action onRejected) + { + return Catch(onRejected); + } + /// /// Add a resolved callback that chains a value promise (optionally converting to a different value type). /// @@ -461,6 +356,11 @@ public IPromise Then(Func onResolved) return Then(onResolved, null); } + IPromiseBase IPromiseBase.Then(Func onResolved) + { + return Then((x) => { onResolved(new PromiseResult(x)); }, null); + } + /// /// Add a resolved callback. /// @@ -469,6 +369,11 @@ public IPromise Then(Action onResolved) return Then(onResolved, null); } + IPromiseBase IPromiseBase.Then(Action onResolved) + { + return Then((x) => { onResolved(new PromiseResult(x)); }, null); + } + /// /// Add a resolved callback and a rejected callback. /// The resolved callback chains a value promise (optionally converting to a different value type). @@ -477,7 +382,7 @@ public IPromise Then(Func onResolved); +// Argument.NotNull(() => onResolved); var resultPromise = new Promise(); resultPromise.WithName(Name); @@ -547,6 +452,11 @@ public IPromise Then(Func onResolved, Action onR return resultPromise; } + IPromiseBase IPromiseBase.Then(Func onResolved, Action onRejected) + { + return Then((x) => { onResolved(new PromiseResult(x)); }, onRejected); + } + /// /// Add a resolved callback and a rejected callback. /// @@ -580,6 +490,11 @@ public IPromise Then(Action onResolved, Action return resultPromise; } + IPromiseBase IPromiseBase.Then(Action onResolved, Action onRejected) + { + return Then((x) => { onResolved(new PromiseResult(x)); }, onRejected); + } + /// /// Return a new promise with a different value. /// May also change the type of the value. @@ -643,6 +558,11 @@ public IPromise ThenAll(Func> chain) return Then(value => Promise.All(chain(value))); } + IPromiseBase IPromiseBase.ThenAll(Func> chain) + { + return ThenAll((x) => { return chain(); }); + } + /// /// Returns a promise that resolves when all of the promises in the enumerable argument have resolved. /// Returns a promise of a collection of the resolved results. @@ -788,4 +708,4 @@ public static IPromise Rejected(Exception ex) return promise; } } -} \ No newline at end of file +} diff --git a/Promise_Base.cs b/Promise_Base.cs new file mode 100644 index 0000000..324a0a4 --- /dev/null +++ b/Promise_Base.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using RSG.Promises; + +namespace RSG +{ + public interface IPromiseBase + { + /// + /// ID of the promise, useful for debugging. + /// + int Id { get; } + + /// + /// Set the name of the promise, useful for debugging. + /// + IPromiseBase WithName(string name); + + /// + /// Completes the promise. + /// onResolved is called on successful completion. + /// onRejected is called on error. + /// + void Done(Action onResolved, Action onRejected); + + /// + /// Completes the promise. + /// onResolved is called on successful completion. + /// Adds a default error handler. + /// + void Done(Action onResolved); + + /// + /// Complete the promise. Adds a default error handler. + /// + void Done(); + + /// + /// Handle errors for the promise. + /// + IPromiseBase Catch(Action onRejected); + + /// + /// Add a resolved callback that chains a non-value promise. + /// + IPromiseBase Then(Func onResolved); + + /// + /// Add a resolved callback. + /// + IPromiseBase Then(Action onResolved); + + /// + /// Add a resolved callback and a rejected callback. + /// The resolved callback chains a non-value promise. + /// + IPromiseBase Then(Func onResolved, Action onRejected); + + /// + /// Add a resolved callback and a rejected callback. + /// + IPromiseBase Then(Action onResolved, Action onRejected); + + /// + /// Chain an enumerable of promises, all of which must resolve. + /// The resulting promise is resolved when all of the promises have resolved. + /// It is rejected as soon as any of the promises have been rejected. + /// + IPromiseBase ThenAll(Func> chain); + } + + /// + /// Interface for a promise that can be rejected. + /// + public interface IRejectable + { + /// + /// Reject the promise with an exception. + /// + void Reject(Exception ex); + } + + /// + /// Arguments to the UnhandledError event. + /// + public class ExceptionEventArgs : EventArgs + { + internal ExceptionEventArgs(Exception exception) + { + // Argument.NotNull(() => exception); + + this.Exception = exception; + } + + public Exception Exception + { + get; + private set; + } + } + + /// + /// Represents a handler invoked when the promise is rejected. + /// + public struct RejectHandler + { + /// + /// Callback fn. + /// + public Action callback; + + /// + /// The promise that is rejected when there is an error while invoking the handler. + /// + public IRejectable rejectable; + } + + public struct PromiseResult + { + public static readonly PromiseResult None = new PromiseResult(); + + public readonly bool hasValue; + public readonly object result; + + public PromiseResult(object value) + { + hasValue = true; + result = value; + } + } + + /// + /// Specifies the state of a promise. + /// + public enum PromiseState + { + Pending, // The promise is in-flight. + Rejected, // The promise has been rejected. + Resolved // The promise has been resolved. + }; + + /// + /// Used to list information of pending promises. + /// + public interface IPromiseInfo + { + /// + /// Id of the promise. + /// + int Id { get; } + + /// + /// Human-readable name for the promise. + /// + string Name { get; } + } + + public abstract class Promise_Base : IPromiseInfo + { + /// + /// Id for the next promise that is created. + /// + private static int nextPromiseId = 0; + + /// + /// The exception when the promise is rejected. + /// + protected Exception rejectionException; + + /// + /// Error handlers. + /// + protected List rejectHandlers; + + /// + /// ID of the promise, useful for debugging. + /// + public int Id { get; } + + /// + /// Name of the promise, when set, useful for debugging. + /// + public string Name { get; protected set; } + + /// + /// Tracks the current state of the promise. + /// + public PromiseState CurState { get; protected set; } + + public Promise_Base() + { + this.CurState = PromiseState.Pending; + this.Id = NextId(); + + if (Promise.EnablePromiseTracking) + { + Promise.pendingPromises.Add(this); + } + } + + /// + /// Increments the ID counter and gives us the ID for the next promise. + /// + internal static int NextId() + { + return ++nextPromiseId; + } + + /// + /// Add a rejection handler for this promise. + /// + protected void AddRejectHandler(Action onRejected, IRejectable rejectable) + { + if (rejectHandlers == null) + { + rejectHandlers = new List(); + } + + rejectHandlers.Add(new RejectHandler() + { + callback = onRejected, + rejectable = rejectable + }); + } + + /// + /// Invoke a single handler. + /// + protected void InvokeHandler(Action callback, IRejectable rejectable, T value) + { + // Argument.NotNull(() => callback); + // Argument.NotNull(() => rejectable); + + try + { + callback(value); + } + catch (Exception ex) + { + rejectable.Reject(ex); + } + } + + protected virtual void ClearHandlers() + { + rejectHandlers = null; + } + + /// + /// Invoke all reject handlers. + /// + protected void InvokeRejectHandlers(Exception ex) + { + // Argument.NotNull(() => ex); + + if (rejectHandlers != null) + { + rejectHandlers.Each(handler => InvokeHandler(handler.callback, handler.rejectable, ex)); + } + + ClearHandlers(); + } + + /// + /// Reject the promise with an exception. + /// + public void Reject(Exception ex) + { + // Argument.NotNull(() => ex); + + if (CurState != PromiseState.Pending) + { + throw new ApplicationException("Attempt to reject a promise that is already in state: " + CurState + ", a promise can only be rejected when it is still in state: " + PromiseState.Pending); + } + + rejectionException = ex; + CurState = PromiseState.Rejected; + + if (Promise.EnablePromiseTracking) + { + Promise.pendingPromises.Remove(this); + } + + InvokeRejectHandlers(ex); + } + } +} diff --git a/Promise_NonGeneric.cs b/Promise_NonGeneric.cs index c66ec9b..fecff64 100644 --- a/Promise_NonGeneric.cs +++ b/Promise_NonGeneric.cs @@ -10,41 +10,31 @@ namespace RSG /// Implements a non-generic C# promise, this is a promise that simply resolves without delivering a value. /// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise /// - public interface IPromise + public interface IPromise : IPromiseBase { - /// - /// ID of the promise, useful for debugging. - /// - int Id { get; } - /// /// Set the name of the promise, useful for debugging. /// - IPromise WithName(string name); + new IPromise WithName(string name); /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// onRejected is called on error. /// void Done(Action onResolved, Action onRejected); /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// Adds a default error handler. /// void Done(Action onResolved); /// - /// Complete the promise. Adds a default error handler. + /// Handle errors for the promise. /// - void Done(); - - /// - /// Handle errors for the promise. - /// - IPromise Catch(Action onRejected); + new IPromise Catch(Action onRejected); /// /// Add a resolved callback that chains a value promise (optionally converting to a different value type). @@ -83,7 +73,7 @@ public interface IPromise /// The resulting promise is resolved when all of the promises have resolved. /// It is rejected as soon as any of the promises have been rejected. /// - IPromise ThenAll(Func> chain); + new IPromise ThenAll(Func> chain); /// /// Chain an enumerable of promises, all of which must resolve. @@ -131,62 +121,11 @@ public interface IPendingPromise : IRejectable void Resolve(); } - /// - /// Used to list information of pending promises. - /// - public interface IPromiseInfo - { - /// - /// Id of the promise. - /// - int Id { get; } - - /// - /// Human-readable name for the promise. - /// - string Name { get; } - } - - /// - /// Arguments to the UnhandledError event. - /// - public class ExceptionEventArgs : EventArgs - { - internal ExceptionEventArgs(Exception exception) - { -// Argument.NotNull(() => exception); - - this.Exception = exception; - } - - public Exception Exception - { - get; - private set; - } - } - - /// - /// Represents a handler invoked when the promise is rejected. - /// - public struct RejectHandler - { - /// - /// Callback fn. - /// - public Action callback; - - /// - /// The promise that is rejected when there is an error while invoking the handler. - /// - public IRejectable rejectable; - } - /// /// Implements a non-generic C# promise, this is a promise that simply resolves without delivering a value. /// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise /// - public class Promise : IPromise, IPendingPromise, IPromiseInfo + public class Promise : Promise_Base, IPromise, IPendingPromise { /// /// Set to true to enable tracking of promises. @@ -204,11 +143,6 @@ public static event EventHandler UnhandledException } private static EventHandler unhandlerException; - /// - /// Id for the next promise that is created. - /// - private static int nextPromiseId = 0; - /// /// Information about pending promises. /// @@ -223,16 +157,6 @@ public static IEnumerable GetPendingPromises() return pendingPromises; } - /// - /// The exception when the promise is rejected. - /// - private Exception rejectionException; - - /// - /// Error handlers. - /// - private List rejectHandlers; - /// /// Represents a handler invoked when the promise is resolved. /// @@ -254,40 +178,11 @@ public struct ResolveHandler /// private List resolveHandlers; - /// - /// ID of the promise, useful for debugging. - /// - public int Id { get; } - - /// - /// Name of the promise, when set, useful for debugging. - /// - public string Name { get; private set; } + public Promise() : base() + { } - /// - /// Tracks the current state of the promise. - /// - public PromiseState CurState { get; private set; } - - public Promise() + public Promise(Action> resolver) : this() { - this.CurState = PromiseState.Pending; - this.Id = NextId(); - if (EnablePromiseTracking) - { - pendingPromises.Add(this); - } - } - - public Promise(Action> resolver) - { - this.CurState = PromiseState.Pending; - this.Id = NextId(); - if (EnablePromiseTracking) - { - pendingPromises.Add(this); - } - try { resolver( @@ -304,31 +199,6 @@ public Promise(Action> resolver) } } - /// - /// Increments the ID counter and gives us the ID for the next promise. - /// - internal static int NextId() - { - return ++nextPromiseId; - } - - /// - /// Add a rejection handler for this promise. - /// - private void AddRejectHandler(Action onRejected, IRejectable rejectable) - { - if (rejectHandlers == null) - { - rejectHandlers = new List(); - } - - rejectHandlers.Add(new RejectHandler() - { - callback = onRejected, - rejectable = rejectable - }); - } - /// /// Add a resolve handler for this promise. /// @@ -385,27 +255,12 @@ private void InvokeResolveHandler(Action callback, IRejectable rejectable) /// /// Helper function clear out all handlers after resolution or rejection. /// - private void ClearHandlers() + override protected void ClearHandlers() { - rejectHandlers = null; + base.ClearHandlers(); resolveHandlers = null; } - /// - /// Invoke all reject handlers. - /// - private void InvokeRejectHandlers(Exception ex) - { -// Argument.NotNull(() => ex); - - if (rejectHandlers != null) - { - rejectHandlers.Each(handler => InvokeRejectHandler(handler.callback, handler.rejectable, ex)); - } - - ClearHandlers(); - } - /// /// Invoke all resolve handlers. /// @@ -419,30 +274,6 @@ private void InvokeResolveHandlers() ClearHandlers(); } - /// - /// Reject the promise with an exception. - /// - public void Reject(Exception ex) - { -// Argument.NotNull(() => ex); - - if (CurState != PromiseState.Pending) - { - throw new ApplicationException("Attempt to reject a promise that is already in state: " + CurState + ", a promise can only be rejected when it is still in state: " + PromiseState.Pending); - } - - rejectionException = ex; - CurState = PromiseState.Rejected; - - if (EnablePromiseTracking) - { - pendingPromises.Remove(this); - } - - InvokeRejectHandlers(ex); - } - - /// /// Resolve the promise with a particular value. /// @@ -464,7 +295,7 @@ public void Resolve() } /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// onRejected is called on error. /// @@ -477,14 +308,40 @@ public void Done(Action onResolved, Action onRejected) } /// - /// Completes the promise. + /// Completes the promise. /// onResolved is called on successful completion. /// Adds a default error handler. /// public void Done(Action onResolved) { Then(onResolved) - .Catch(ex => + .Catch(ex => + Promise.PropagateUnhandledException(this, ex) + ); + } + + /// + /// Completes the promise. + /// onResolved is called on successful completion. + /// onRejected is called on error. + /// + void IPromiseBase.Done(Action onResolved, Action onRejected) + { + Then(() => { onResolved(PromiseResult.None); }, onRejected) + .Catch(ex => + Promise.PropagateUnhandledException(this, ex) + ); + } + + /// + /// Completes the promise. + /// onResolved is called on successful completion. + /// Adds a default error handler. + /// + void IPromiseBase.Done(Action onResolved) + { + Then(() => { onResolved(PromiseResult.None); }) + .Catch(ex => Promise.PropagateUnhandledException(this, ex) ); } @@ -508,8 +365,13 @@ public IPromise WithName(string name) return this; } + IPromiseBase IPromiseBase.WithName(string name) + { + return WithName(name); + } + /// - /// Handle errors for the promise. + /// Handle errors for the promise. /// public IPromise Catch(Action onRejected) { @@ -535,6 +397,11 @@ public IPromise Catch(Action onRejected) return resultPromise; } + IPromiseBase IPromiseBase.Catch(Action onRejected) + { + return Catch(onRejected); + } + /// /// Add a resolved callback that chains a value promise (optionally converting to a different value type). /// @@ -551,6 +418,11 @@ public IPromise Then(Func onResolved) return Then(onResolved, null); } + IPromiseBase IPromiseBase.Then(Func onResolved) + { + return Then(() => { onResolved(PromiseResult.None); }); + } + /// /// Add a resolved callback. /// @@ -559,6 +431,11 @@ public IPromise Then(Action onResolved) return Then(onResolved, null); } + IPromiseBase IPromiseBase.Then(Action onResolved) + { + return Then(() => { onResolved(PromiseResult.None); }); + } + /// /// Add a resolved callback and a rejected callback. /// The resolved callback chains a value promise (optionally converting to a different value type). @@ -637,6 +514,11 @@ public IPromise Then(Func onResolved, Action onRejected) return resultPromise; } + IPromiseBase IPromiseBase.Then(Func onResolved, Action onRejected) + { + return Then(() => { onResolved(PromiseResult.None); }, onRejected); + } + /// /// Add a resolved callback and a rejected callback. /// @@ -670,6 +552,11 @@ public IPromise Then(Action onResolved, Action onRejected) return resultPromise; } + IPromiseBase IPromiseBase.Then(Action onResolved, Action onRejected) + { + return Then(() => { onResolved(PromiseResult.None); }, onRejected); + } + /// /// Helper function to invoke or register resolve/reject handlers. /// @@ -700,6 +587,11 @@ public IPromise ThenAll(Func> chain) return Then(() => Promise.All(chain())); } + IPromiseBase IPromiseBase.ThenAll(Func> chain) + { + return ThenAll(chain); + } + /// /// Chain an enumerable of promises, all of which must resolve. /// Converts to a non-value promise. @@ -897,4 +789,4 @@ internal static void PropagateUnhandledException(object sender, Exception ex) } } } -} \ No newline at end of file +} From 6ae92561c86b21f4e61bf175e552fad8443b8822 Mon Sep 17 00:00:00 2001 From: Nathan Loewen Date: Thu, 23 Mar 2017 12:15:15 -0500 Subject: [PATCH 2/2] Add comments to base class function implementations --- Promise.cs | 25 +++++++++++++++++++++++++ Promise_Base.cs | 3 +++ Promise_NonGeneric.cs | 24 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/Promise.cs b/Promise.cs index bfecaf8..3e23218 100644 --- a/Promise.cs +++ b/Promise.cs @@ -303,6 +303,9 @@ public IPromise WithName(string name) return this; } + /// + /// Set the name of the promise, useful for debugging. + /// IPromiseBase IPromiseBase.WithName(string name) { return WithName(name); @@ -335,6 +338,9 @@ public IPromise Catch(Action onRejected) return resultPromise; } + /// + /// Handle errors for the promise. + /// IPromiseBase IPromiseBase.Catch(Action onRejected) { return Catch(onRejected); @@ -356,6 +362,9 @@ public IPromise Then(Func onResolved) return Then(onResolved, null); } + /// + /// Add a resolved callback that chains a non-value promise. + /// IPromiseBase IPromiseBase.Then(Func onResolved) { return Then((x) => { onResolved(new PromiseResult(x)); }, null); @@ -369,6 +378,9 @@ public IPromise Then(Action onResolved) return Then(onResolved, null); } + /// + /// Add a resolved callback. + /// IPromiseBase IPromiseBase.Then(Action onResolved) { return Then((x) => { onResolved(new PromiseResult(x)); }, null); @@ -452,6 +464,10 @@ public IPromise Then(Func onResolved, Action onR return resultPromise; } + /// + /// Add a resolved callback and a rejected callback. + /// The resolved callback chains a non-value promise. + /// IPromiseBase IPromiseBase.Then(Func onResolved, Action onRejected) { return Then((x) => { onResolved(new PromiseResult(x)); }, onRejected); @@ -490,6 +506,9 @@ public IPromise Then(Action onResolved, Action return resultPromise; } + /// + /// Add a resolved callback and a rejected callback. + /// IPromiseBase IPromiseBase.Then(Action onResolved, Action onRejected) { return Then((x) => { onResolved(new PromiseResult(x)); }, onRejected); @@ -558,6 +577,12 @@ public IPromise ThenAll(Func> chain) return Then(value => Promise.All(chain(value))); } + /// + /// Chain an enumerable of promises, all of which must resolve. + /// Converts to a non-value promise. + /// The resulting promise is resolved when all of the promises have resolved. + /// It is rejected as soon as any of the promises have been rejected. + /// IPromiseBase IPromiseBase.ThenAll(Func> chain) { return ThenAll((x) => { return chain(); }); diff --git a/Promise_Base.cs b/Promise_Base.cs index 324a0a4..7e2cc2b 100644 --- a/Promise_Base.cs +++ b/Promise_Base.cs @@ -115,6 +115,9 @@ public struct RejectHandler public IRejectable rejectable; } + /// + /// Option type for generic access to promised data + /// public struct PromiseResult { public static readonly PromiseResult None = new PromiseResult(); diff --git a/Promise_NonGeneric.cs b/Promise_NonGeneric.cs index fecff64..d9b0cf6 100644 --- a/Promise_NonGeneric.cs +++ b/Promise_NonGeneric.cs @@ -365,6 +365,9 @@ public IPromise WithName(string name) return this; } + /// + /// Set the name of the promise, useful for debugging. + /// IPromiseBase IPromiseBase.WithName(string name) { return WithName(name); @@ -397,6 +400,9 @@ public IPromise Catch(Action onRejected) return resultPromise; } + /// + /// Handle errors for the promise. + /// IPromiseBase IPromiseBase.Catch(Action onRejected) { return Catch(onRejected); @@ -418,6 +424,9 @@ public IPromise Then(Func onResolved) return Then(onResolved, null); } + /// + /// Add a resolved callback that chains a non-value promise. + /// IPromiseBase IPromiseBase.Then(Func onResolved) { return Then(() => { onResolved(PromiseResult.None); }); @@ -431,6 +440,9 @@ public IPromise Then(Action onResolved) return Then(onResolved, null); } + /// + /// Add a resolved callback. + /// IPromiseBase IPromiseBase.Then(Action onResolved) { return Then(() => { onResolved(PromiseResult.None); }); @@ -514,6 +526,10 @@ public IPromise Then(Func onResolved, Action onRejected) return resultPromise; } + /// + /// Add a resolved callback and a rejected callback. + /// The resolved callback chains a non-value promise. + /// IPromiseBase IPromiseBase.Then(Func onResolved, Action onRejected) { return Then(() => { onResolved(PromiseResult.None); }, onRejected); @@ -552,6 +568,9 @@ public IPromise Then(Action onResolved, Action onRejected) return resultPromise; } + /// + /// Add a resolved callback and a rejected callback. + /// IPromiseBase IPromiseBase.Then(Action onResolved, Action onRejected) { return Then(() => { onResolved(PromiseResult.None); }, onRejected); @@ -587,6 +606,11 @@ public IPromise ThenAll(Func> chain) return Then(() => Promise.All(chain())); } + /// + /// Chain an enumerable of promises, all of which must resolve. + /// The resulting promise is resolved when all of the promises have resolved. + /// It is rejected as soon as any of the promises have been rejected. + /// IPromiseBase IPromiseBase.ThenAll(Func> chain) { return ThenAll(chain);