Mercurial > pub > ImplabNet
diff Implab/Promise.cs @ 11:6ec82bf68c8e promises
refactoring
author | cin |
---|---|
date | Tue, 05 Nov 2013 01:09:58 +0400 |
parents | aa33d0bb8c0c |
children | e943453e5039 |
line wrap: on
line diff
--- a/Implab/Promise.cs Sun Nov 03 18:07:38 2013 +0400 +++ b/Implab/Promise.cs Tue Nov 05 01:09:58 2013 +0400 @@ -7,7 +7,7 @@ namespace Implab { public delegate void ErrorHandler(Exception e); - + public delegate T ErrorHandler<out T>(Exception e); public delegate void ResultHandler<in T>(T result); public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result); public delegate Promise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result); @@ -126,52 +126,18 @@ return Cancel(true); } - protected virtual void OnStateChanged() { - switch (m_state) { - case PromiseState.Resolved: - foreach (var resultHandlerInfo in m_resultHandlers) - try { - if (resultHandlerInfo.resultHandler != null) - resultHandlerInfo.resultHandler(m_result); - } catch (Exception e) { - try { - if (resultHandlerInfo.errorHandler != null) - resultHandlerInfo.errorHandler(e); - } catch { } - } - break; - case PromiseState.Cancelled: - foreach (var cancelHandler in m_cancelHandlers) - cancelHandler(); - break; - case PromiseState.Rejected: - foreach (var resultHandlerInfo in m_resultHandlers) - try { - if (resultHandlerInfo.errorHandler != null) - resultHandlerInfo.errorHandler(m_error); - } catch { } - break; - default: - throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state)); - } - - m_resultHandlers = null; - m_cancelHandlers = null; - } - /// <summary> - /// Добавляет обработчики событий выполнения обещания. + /// Adds new handlers to this promise. /// </summary> - /// <param name="success">Обработчик успешного выполнения обещания. - /// Данному обработчику будет передан результат выполнения операции.</param> - /// <param name="error">Обработчик ошибки. Данный обработчик получит - /// исключение возникшее при выполнении операции.</param> - /// <returns>Само обещание</returns> + /// <param name="success">The handler of the successfully completed operation. + /// This handler will recieve an operation result as a parameter.</param> + /// <param name="error">Handles an exception that may occur during the operation.</param> + /// <returns>The new promise chained to this one.</returns> public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) { if (success == null && error == null) return this; - var medium = new Promise<T>(); + var medium = new Promise<T>(this, true); var handlerInfo = new ResultHandlerInfo(); @@ -198,14 +164,99 @@ return medium; } + /// <summary> + /// Adds new handlers to this promise. + /// </summary> + /// <param name="success">The handler of the successfully completed operation. + /// This handler will recieve an operation result as a parameter.</param> + /// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param> + /// <returns>The new promise chained to this one.</returns> + public Promise<T> Then(ResultHandler<T> success, ErrorHandler<T> error) { + if (success == null && error == null) + return this; + + var medium = new Promise<T>(this, true); + + var handlerInfo = new ResultHandlerInfo(); + + if (success != null) + handlerInfo.resultHandler = x => { + success(x); + medium.Resolve(x); + }; + else + handlerInfo.resultHandler = medium.Resolve; + + if (error != null) + handlerInfo.errorHandler = x => { + try { + medium.Resolve(error(x)); + } catch { } + medium.Reject(x); + }; + else + handlerInfo.errorHandler = medium.Reject; + + AddHandler(handlerInfo); + + return medium; + } + + public Promise<T> Then(ResultHandler<T> success) { - return Then(success, null); + if (success == null) + return this; + + var medium = new Promise<T>(this, true); + + var handlerInfo = new ResultHandlerInfo(); + + if (success != null) + handlerInfo.resultHandler = x => { + success(x); + medium.Resolve(x); + }; + else + handlerInfo.resultHandler = medium.Resolve; + + handlerInfo.errorHandler = medium.Reject; + + AddHandler(handlerInfo); + + return medium; } public Promise<T> Error(ErrorHandler error) { return Then(null, error); } + /// <summary> + /// Handles error and allows to keep the promise. + /// </summary> + /// <remarks> + /// If the specified handler throws an exception, this exception will be used to reject the promise. + /// </remarks> + /// <param name="handler">The error handler which returns the result of the promise.</param> + /// <returns>New promise.</returns> + public Promise<T> Error(ErrorHandler<T> handler) { + if (handler == null) + return this; + + var medium = new Promise<T>(this, true); + + AddHandler(new ResultHandlerInfo { + errorHandler = e => { + try { + medium.Resolve(handler(e)); + } catch (Exception e2) { + medium.Reject(e2); + } + } + }); + + return medium; + } + public Promise<T> Anyway(Action handler) { if (handler == null) return this; @@ -295,9 +346,9 @@ // notify chained operation that it's not needed medium.Cancelled(() => promise.Cancel()); promise.Then( - medium.Resolve, - medium.Reject - ); + x => medium.Resolve(x), + e => medium.Reject(e) + ); }, errorHandler = delegate(Exception e) { if (error != null) @@ -416,6 +467,39 @@ } } + protected virtual void OnStateChanged() { + switch (m_state) { + case PromiseState.Resolved: + foreach (var resultHandlerInfo in m_resultHandlers) + try { + if (resultHandlerInfo.resultHandler != null) + resultHandlerInfo.resultHandler(m_result); + } catch (Exception e) { + try { + if (resultHandlerInfo.errorHandler != null) + resultHandlerInfo.errorHandler(e); + } catch { } + } + break; + case PromiseState.Cancelled: + foreach (var cancelHandler in m_cancelHandlers) + cancelHandler(); + break; + case PromiseState.Rejected: + foreach (var resultHandlerInfo in m_resultHandlers) + try { + if (resultHandlerInfo.errorHandler != null) + resultHandlerInfo.errorHandler(m_error); + } catch { } + break; + default: + throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state)); + } + + m_resultHandlers = null; + m_cancelHandlers = null; + } + public bool IsExclusive { @@ -434,7 +518,7 @@ } } - public bool Cancel(bool dependencies) { + protected bool Cancel(bool dependencies) { bool result; lock (m_lock) { @@ -450,7 +534,7 @@ OnStateChanged(); if (dependencies && m_parent != null && m_parent.IsExclusive) { - m_parent.Cancel(true); + m_parent.Cancel(); } return result;